qontract-reconcile 0.10.2.dev334__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.dev334.dist-info → qontract_reconcile-0.10.2.dev439.dist-info}/METADATA +13 -12
- {qontract_reconcile-0.10.2.dev334.dist-info → qontract_reconcile-0.10.2.dev439.dist-info}/RECORD +366 -361
- 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 +3 -3
- 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 +6 -12
- 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 +11 -3
- reconcile/cli.py +111 -18
- reconcile/dashdotdb_dora.py +5 -12
- reconcile/dashdotdb_slo.py +1 -1
- reconcile/database_access_manager.py +123 -117
- reconcile/dynatrace_token_provider/integration.py +1 -1
- reconcile/endpoints_discovery/integration.py +4 -1
- reconcile/endpoints_discovery/merge_request.py +1 -1
- reconcile/endpoints_discovery/merge_request_manager.py +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 +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 +3207 -1683
- 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 +440 -407
- 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_worker_fleets.py +10 -8
- 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 +113 -5
- reconcile/openshift_cluster_bots.py +3 -2
- reconcile/openshift_namespace_labels.py +1 -1
- reconcile/openshift_namespaces.py +97 -101
- reconcile/openshift_resources_base.py +6 -2
- reconcile/openshift_rhcs_certs.py +74 -37
- 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 +2 -2
- 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/prometheus_rules_tester/integration.py +3 -3
- reconcile/quay_mirror.py +1 -1
- reconcile/queries.py +131 -0
- reconcile/rhidp/common.py +3 -5
- reconcile/rhidp/sso_client/base.py +16 -5
- reconcile/saas_auto_promotions_manager/merge_request_manager/renderer.py +1 -1
- reconcile/saas_auto_promotions_manager/subscriber.py +4 -3
- reconcile/skupper_network/integration.py +2 -2
- reconcile/slack_usergroups.py +35 -14
- reconcile/sql_query.py +1 -0
- reconcile/status_board.py +6 -6
- reconcile/statuspage/atlassian.py +7 -7
- reconcile/statuspage/integrations/maintenances.py +4 -3
- reconcile/statuspage/page.py +4 -9
- reconcile/statuspage/status.py +5 -8
- reconcile/templates/rosa-classic-cluster-creation.sh.j2 +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 +7 -1
- reconcile/terraform_cloudflare_dns.py +3 -3
- reconcile/terraform_cloudflare_resources.py +5 -5
- reconcile/terraform_cloudflare_users.py +3 -2
- reconcile/terraform_init/integration.py +187 -23
- reconcile/terraform_repo.py +16 -12
- reconcile/terraform_resources.py +17 -7
- reconcile/terraform_tgw_attachments.py +27 -19
- reconcile/terraform_users.py +7 -0
- reconcile/terraform_vpc_peerings.py +14 -3
- reconcile/terraform_vpc_resources/integration.py +20 -8
- reconcile/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/gql.py +4 -7
- reconcile/utils/helm.py +2 -1
- reconcile/utils/helpers.py +1 -1
- reconcile/utils/instrumented_wrappers.py +1 -1
- reconcile/utils/internal_groups/client.py +2 -2
- reconcile/utils/internal_groups/models.py +8 -17
- reconcile/utils/jinja2/utils.py +6 -8
- reconcile/utils/jira_client.py +82 -63
- reconcile/utils/jjb_client.py +28 -15
- reconcile/utils/jobcontroller/controller.py +2 -2
- reconcile/utils/jobcontroller/models.py +17 -1
- reconcile/utils/json.py +74 -0
- reconcile/utils/membershipsources/app_interface_resolver.py +4 -2
- reconcile/utils/membershipsources/models.py +16 -23
- reconcile/utils/membershipsources/resolver.py +4 -2
- reconcile/utils/merge_request_manager/merge_request_manager.py +4 -4
- reconcile/utils/merge_request_manager/parser.py +6 -6
- reconcile/utils/metrics.py +5 -5
- reconcile/utils/models.py +304 -82
- reconcile/utils/mr/app_interface_reporter.py +2 -2
- reconcile/utils/mr/base.py +2 -2
- reconcile/utils/mr/notificator.py +3 -3
- reconcile/utils/mr/update_access_report_base.py +3 -4
- reconcile/utils/mr/user_maintenance.py +3 -2
- reconcile/utils/oc.py +249 -203
- 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/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/openshift_resource.py +10 -5
- 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 +1 -1
- reconcile/utils/rhcsv2_certs.py +138 -35
- reconcile/utils/rosa/session.py +16 -0
- reconcile/utils/runtime/integration.py +2 -3
- reconcile/utils/runtime/runner.py +2 -2
- reconcile/utils/saasherder/interfaces.py +13 -20
- reconcile/utils/saasherder/models.py +25 -21
- reconcile/utils/saasherder/saasherder.py +55 -31
- reconcile/utils/slack_api.py +26 -4
- reconcile/utils/sloth.py +224 -0
- reconcile/utils/sqs_gateway.py +2 -1
- reconcile/utils/state.py +2 -1
- reconcile/utils/structs.py +1 -1
- reconcile/utils/terraform_client.py +5 -4
- reconcile/utils/terrascript_aws_client.py +192 -114
- reconcile/utils/unleash/server.py +2 -8
- reconcile/utils/vault.py +5 -12
- reconcile/utils/vcs.py +8 -8
- reconcile/vault_replication.py +107 -42
- 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/systems_and_tools.py +5 -1
- tools/qontract_cli.py +31 -18
- tools/template_validation.py +3 -1
- reconcile/gql_definitions/cna/__init__.py +0 -0
- reconcile/gql_definitions/cna/queries/__init__.py +0 -0
- reconcile/gql_definitions/ocm_oidc_idp/__init__.py +0 -0
- reconcile/gql_definitions/ocm_subscription_labels/__init__.py +0 -0
- {qontract_reconcile-0.10.2.dev334.dist-info → qontract_reconcile-0.10.2.dev439.dist-info}/WHEEL +0 -0
- {qontract_reconcile-0.10.2.dev334.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-.]+$")
|
|
@@ -286,12 +292,6 @@ SUPPORTED_ALB_LISTENER_RULE_CONDITION_TYPE_MAPPING = {
|
|
|
286
292
|
"source-ip": "source_ip",
|
|
287
293
|
}
|
|
288
294
|
|
|
289
|
-
DEFAULT_TAGS = {
|
|
290
|
-
"tags": {
|
|
291
|
-
"app": "app-sre-infra",
|
|
292
|
-
},
|
|
293
|
-
}
|
|
294
|
-
|
|
295
295
|
AWS_ELB_ACCOUNT_IDS = {
|
|
296
296
|
"us-east-1": "127311923021",
|
|
297
297
|
"us-east-2": "033677994240",
|
|
@@ -374,6 +374,10 @@ class aws_s3_bucket_logging(Resource):
|
|
|
374
374
|
pass
|
|
375
375
|
|
|
376
376
|
|
|
377
|
+
class aws_kinesis_resource_policy(Resource):
|
|
378
|
+
pass
|
|
379
|
+
|
|
380
|
+
|
|
377
381
|
class aws_cloudfront_log_delivery_canonical_user_id(Data):
|
|
378
382
|
pass
|
|
379
383
|
|
|
@@ -475,6 +479,7 @@ class TerrascriptClient:
|
|
|
475
479
|
integration_prefix: str,
|
|
476
480
|
thread_pool_size: int,
|
|
477
481
|
accounts: Iterable[MutableMapping[str, Any]],
|
|
482
|
+
default_tags: Mapping[str, str] | None,
|
|
478
483
|
settings: Mapping[str, Any] | None = None,
|
|
479
484
|
prefetch_resources_by_schemas: Iterable[str] | None = None,
|
|
480
485
|
secret_reader: SecretReaderBase | None = None,
|
|
@@ -488,6 +493,7 @@ class TerrascriptClient:
|
|
|
488
493
|
else:
|
|
489
494
|
self.secret_reader = SecretReader(settings=settings)
|
|
490
495
|
self.configs: dict[str, dict] = {}
|
|
496
|
+
self.default_tags = default_tags or {"app": "app-sre-infra"}
|
|
491
497
|
self.populate_configs(filtered_accounts)
|
|
492
498
|
self.versions: dict[str, str] = {
|
|
493
499
|
a["name"]: a["providerVersion"] for a in filtered_accounts
|
|
@@ -508,7 +514,7 @@ class TerrascriptClient:
|
|
|
508
514
|
region=region,
|
|
509
515
|
alias=region,
|
|
510
516
|
skip_region_validation=True,
|
|
511
|
-
default_tags=
|
|
517
|
+
default_tags={"tags": config["tags"]},
|
|
512
518
|
)
|
|
513
519
|
|
|
514
520
|
# Add default region, which will be in resourcesDefaultRegion
|
|
@@ -517,7 +523,7 @@ class TerrascriptClient:
|
|
|
517
523
|
secret_key=config["aws_secret_access_key"],
|
|
518
524
|
region=config["resourcesDefaultRegion"],
|
|
519
525
|
skip_region_validation=True,
|
|
520
|
-
default_tags=
|
|
526
|
+
default_tags={"tags": config["tags"]},
|
|
521
527
|
)
|
|
522
528
|
|
|
523
529
|
ts += Terraform(
|
|
@@ -800,6 +806,9 @@ class TerrascriptClient:
|
|
|
800
806
|
config["supportedDeploymentRegions"] = account["supportedDeploymentRegions"]
|
|
801
807
|
config["resourcesDefaultRegion"] = account["resourcesDefaultRegion"]
|
|
802
808
|
config["terraformState"] = account["terraformState"]
|
|
809
|
+
config["tags"] = dict(self.default_tags) | get_aws_account_tags(
|
|
810
|
+
account.get("organization", None)
|
|
811
|
+
)
|
|
803
812
|
self.configs[account_name] = config
|
|
804
813
|
|
|
805
814
|
def _get_partition(self, account: str) -> str:
|
|
@@ -1054,7 +1063,9 @@ class TerrascriptClient:
|
|
|
1054
1063
|
ignore_changes = (
|
|
1055
1064
|
"all" if "all" in lifecycle.ignore_changes else lifecycle.ignore_changes
|
|
1056
1065
|
)
|
|
1057
|
-
return lifecycle.
|
|
1066
|
+
return lifecycle.model_dump(by_alias=True) | {
|
|
1067
|
+
"ignore_changes": ignore_changes
|
|
1068
|
+
}
|
|
1058
1069
|
return None
|
|
1059
1070
|
|
|
1060
1071
|
def populate_additional_providers(
|
|
@@ -1069,25 +1080,15 @@ class TerrascriptClient:
|
|
|
1069
1080
|
config = self.configs[account_name]
|
|
1070
1081
|
existing_provider_aliases = {p.get("alias") for p in ts["provider"]["aws"]}
|
|
1071
1082
|
if alias not in existing_provider_aliases:
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
)
|
|
1082
|
-
else:
|
|
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=DEFAULT_TAGS,
|
|
1090
|
-
)
|
|
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
|
+
)
|
|
1091
1092
|
|
|
1092
1093
|
def populate_route53(
|
|
1093
1094
|
self, desired_state: Iterable[Mapping[str, Any]], default_ttl: int = 300
|
|
@@ -1430,7 +1431,7 @@ class TerrascriptClient:
|
|
|
1430
1431
|
req_account_name = req_account.name
|
|
1431
1432
|
# Accepter's side of the connection - the cluster's account
|
|
1432
1433
|
acc_account = accepter.account
|
|
1433
|
-
acc_alias = self.get_provider_alias(acc_account.
|
|
1434
|
+
acc_alias = self.get_provider_alias(acc_account.model_dump(by_alias=True))
|
|
1434
1435
|
acc_uid = acc_account.uid
|
|
1435
1436
|
if acc_account.assume_role:
|
|
1436
1437
|
acc_uid = awsh.get_account_uid_from_arn(acc_account.assume_role)
|
|
@@ -1947,7 +1948,7 @@ class TerrascriptClient:
|
|
|
1947
1948
|
em_identifier = f"{identifier}-enhanced-monitoring"
|
|
1948
1949
|
em_values = {
|
|
1949
1950
|
"name": em_identifier,
|
|
1950
|
-
"assume_role_policy":
|
|
1951
|
+
"assume_role_policy": json_dumps(assume_role_policy),
|
|
1951
1952
|
}
|
|
1952
1953
|
role_tf_resource = aws_iam_role(em_identifier, **em_values)
|
|
1953
1954
|
tf_resources.append(role_tf_resource)
|
|
@@ -2216,6 +2217,43 @@ class TerrascriptClient:
|
|
|
2216
2217
|
letters_and_digits = string.ascii_letters + string.digits
|
|
2217
2218
|
return "".join(random.choice(letters_and_digits) for i in range(string_length))
|
|
2218
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
|
+
|
|
2219
2257
|
def populate_tf_resource_s3(self, spec: ExternalResourceSpec) -> aws_s3_bucket:
|
|
2220
2258
|
account = spec.provisioner_name
|
|
2221
2259
|
identifier = spec.identifier
|
|
@@ -2255,47 +2293,11 @@ class TerrascriptClient:
|
|
|
2255
2293
|
request_payer = common_values.get("request_payer")
|
|
2256
2294
|
if request_payer:
|
|
2257
2295
|
values["request_payer"] = request_payer
|
|
2258
|
-
lifecycle_rules
|
|
2259
|
-
|
|
2260
|
-
|
|
2296
|
+
if lifecycle_rules := self._build_tf_resource_s3_lifecycle_rules(
|
|
2297
|
+
versioning=versioning,
|
|
2298
|
+
common_values=common_values,
|
|
2299
|
+
):
|
|
2261
2300
|
values["lifecycle_rule"] = lifecycle_rules
|
|
2262
|
-
if versioning:
|
|
2263
|
-
lrs = values.get("lifecycle_rule", [])
|
|
2264
|
-
expiration_rule = False
|
|
2265
|
-
for lr in lrs:
|
|
2266
|
-
if "noncurrent_version_expiration" in lr:
|
|
2267
|
-
expiration_rule = True
|
|
2268
|
-
break
|
|
2269
|
-
if not expiration_rule:
|
|
2270
|
-
# Add a default noncurrent object expiration rule if
|
|
2271
|
-
# if one isn't already set
|
|
2272
|
-
rule = {
|
|
2273
|
-
"id": "expire_noncurrent_versions",
|
|
2274
|
-
"enabled": "true",
|
|
2275
|
-
"noncurrent_version_expiration": {"days": 30},
|
|
2276
|
-
}
|
|
2277
|
-
if len(lrs) > 0:
|
|
2278
|
-
lrs.append(rule)
|
|
2279
|
-
else:
|
|
2280
|
-
lrs = rule
|
|
2281
|
-
sc = common_values.get("storage_class")
|
|
2282
|
-
if sc:
|
|
2283
|
-
sc = sc.upper()
|
|
2284
|
-
days = "1"
|
|
2285
|
-
if sc.endswith("_IA"):
|
|
2286
|
-
# Infrequent Access storage class has minimum 30 days
|
|
2287
|
-
# before transition
|
|
2288
|
-
days = "30"
|
|
2289
|
-
rule = {
|
|
2290
|
-
"id": sc + "_storage_class",
|
|
2291
|
-
"enabled": "true",
|
|
2292
|
-
"transition": {"days": days, "storage_class": sc},
|
|
2293
|
-
"noncurrent_version_transition": {"days": days, "storage_class": sc},
|
|
2294
|
-
}
|
|
2295
|
-
if values.get("lifecycle_rule"):
|
|
2296
|
-
values["lifecycle_rule"].append(rule)
|
|
2297
|
-
else:
|
|
2298
|
-
values["lifecycle_rule"] = rule
|
|
2299
2301
|
cors_rules = common_values.get("cors_rules")
|
|
2300
2302
|
if cors_rules:
|
|
2301
2303
|
# common_values['cors_rules'] is a list of cors_rules
|
|
@@ -2345,7 +2347,7 @@ class TerrascriptClient:
|
|
|
2345
2347
|
}
|
|
2346
2348
|
],
|
|
2347
2349
|
}
|
|
2348
|
-
rc_values["assume_role_policy"] =
|
|
2350
|
+
rc_values["assume_role_policy"] = json_dumps(role)
|
|
2349
2351
|
role_resource = aws_iam_role(id, **rc_values)
|
|
2350
2352
|
tf_resources.append(role_resource)
|
|
2351
2353
|
|
|
@@ -2383,7 +2385,7 @@ class TerrascriptClient:
|
|
|
2383
2385
|
},
|
|
2384
2386
|
],
|
|
2385
2387
|
}
|
|
2386
|
-
rc_values["policy"] =
|
|
2388
|
+
rc_values["policy"] = json_dumps(policy)
|
|
2387
2389
|
policy_resource = aws_iam_policy(id, **rc_values)
|
|
2388
2390
|
tf_resources.append(policy_resource)
|
|
2389
2391
|
|
|
@@ -2598,7 +2600,7 @@ class TerrascriptClient:
|
|
|
2598
2600
|
},
|
|
2599
2601
|
],
|
|
2600
2602
|
}
|
|
2601
|
-
values["policy"] =
|
|
2603
|
+
values["policy"] = json_dumps(policy)
|
|
2602
2604
|
values["depends_on"] = self.get_dependencies([user_tf_resource])
|
|
2603
2605
|
|
|
2604
2606
|
tf_aws_iam_policy = aws_iam_policy(identifier, **values)
|
|
@@ -2877,7 +2879,7 @@ class TerrascriptClient:
|
|
|
2877
2879
|
values: dict[str, Any] = {
|
|
2878
2880
|
"name": identifier,
|
|
2879
2881
|
"tags": common_values["tags"],
|
|
2880
|
-
"assume_role_policy":
|
|
2882
|
+
"assume_role_policy": json_dumps(assume_role_policy),
|
|
2881
2883
|
}
|
|
2882
2884
|
|
|
2883
2885
|
inline_policy = common_values.get("inline_policy")
|
|
@@ -2931,7 +2933,7 @@ class TerrascriptClient:
|
|
|
2931
2933
|
self, account: str, name: str, policy: Mapping[str, Any]
|
|
2932
2934
|
) -> None:
|
|
2933
2935
|
tf_aws_iam_policy = aws_iam_policy(
|
|
2934
|
-
f"{account}-{name}", name=name, policy=
|
|
2936
|
+
f"{account}-{name}", name=name, policy=json_dumps(policy)
|
|
2935
2937
|
)
|
|
2936
2938
|
self.add_resource(account, tf_aws_iam_policy)
|
|
2937
2939
|
|
|
@@ -2973,7 +2975,7 @@ class TerrascriptClient:
|
|
|
2973
2975
|
role_tf_resource = aws_iam_role(
|
|
2974
2976
|
f"{account}-{name}",
|
|
2975
2977
|
name=name,
|
|
2976
|
-
assume_role_policy=
|
|
2978
|
+
assume_role_policy=json_dumps(assume_role_policy),
|
|
2977
2979
|
managed_policy_arns=managed_policy_arns,
|
|
2978
2980
|
max_session_duration=max_session_duration_hours * 3600,
|
|
2979
2981
|
)
|
|
@@ -3017,7 +3019,7 @@ class TerrascriptClient:
|
|
|
3017
3019
|
all_queues.append(queue_name)
|
|
3018
3020
|
sqs_policy = values.pop("sqs_policy", None)
|
|
3019
3021
|
if sqs_policy is not None:
|
|
3020
|
-
values["policy"] =
|
|
3022
|
+
values["policy"] = json_dumps(sqs_policy)
|
|
3021
3023
|
dl_queue = values.pop("dl_queue", None)
|
|
3022
3024
|
if dl_queue is not None:
|
|
3023
3025
|
max_receive_count = int(values.pop("max_receive_count", 10))
|
|
@@ -3031,9 +3033,7 @@ class TerrascriptClient:
|
|
|
3031
3033
|
"deadLetterTargetArn": "${" + dl_data.arn + "}",
|
|
3032
3034
|
"maxReceiveCount": max_receive_count,
|
|
3033
3035
|
}
|
|
3034
|
-
values["redrive_policy"] =
|
|
3035
|
-
redrive_policy, sort_keys=True
|
|
3036
|
-
)
|
|
3036
|
+
values["redrive_policy"] = json_dumps(redrive_policy)
|
|
3037
3037
|
kms_master_key_id = values.pop("kms_master_key_id", None)
|
|
3038
3038
|
if kms_master_key_id is not None:
|
|
3039
3039
|
if kms_master_key_id.startswith("arn:"):
|
|
@@ -3106,7 +3106,7 @@ class TerrascriptClient:
|
|
|
3106
3106
|
"Resource": list(kms_keys),
|
|
3107
3107
|
}
|
|
3108
3108
|
policy["Statement"].append(kms_statement)
|
|
3109
|
-
values["policy"] =
|
|
3109
|
+
values["policy"] = json_dumps(policy)
|
|
3110
3110
|
policy_tf_resource = aws_iam_policy(policy_identifier, **values)
|
|
3111
3111
|
tf_resources.append(policy_tf_resource)
|
|
3112
3112
|
|
|
@@ -3256,7 +3256,7 @@ class TerrascriptClient:
|
|
|
3256
3256
|
}
|
|
3257
3257
|
],
|
|
3258
3258
|
}
|
|
3259
|
-
values["policy"] =
|
|
3259
|
+
values["policy"] = json_dumps(policy)
|
|
3260
3260
|
values["depends_on"] = self.get_dependencies([user_tf_resource])
|
|
3261
3261
|
|
|
3262
3262
|
tf_aws_iam_policy = aws_iam_policy(identifier, **values)
|
|
@@ -3366,7 +3366,7 @@ class TerrascriptClient:
|
|
|
3366
3366
|
},
|
|
3367
3367
|
],
|
|
3368
3368
|
}
|
|
3369
|
-
values_policy["policy"] =
|
|
3369
|
+
values_policy["policy"] = json_dumps(policy)
|
|
3370
3370
|
values_policy["depends_on"] = self.get_dependencies([user_tf_resource])
|
|
3371
3371
|
|
|
3372
3372
|
tf_aws_iam_policy = aws_iam_policy(identifier, **values_policy)
|
|
@@ -3416,7 +3416,7 @@ class TerrascriptClient:
|
|
|
3416
3416
|
}
|
|
3417
3417
|
],
|
|
3418
3418
|
}
|
|
3419
|
-
values_policy["policy"] =
|
|
3419
|
+
values_policy["policy"] = json_dumps(policy)
|
|
3420
3420
|
values_policy["depends_on"] = self.get_dependencies([bucket_tf_resource])
|
|
3421
3421
|
region = common_values.get("region") or self.default_regions.get(account)
|
|
3422
3422
|
assert region # make mypy happy
|
|
@@ -3562,7 +3562,7 @@ class TerrascriptClient:
|
|
|
3562
3562
|
}
|
|
3563
3563
|
],
|
|
3564
3564
|
}
|
|
3565
|
-
sqs_values["policy"] =
|
|
3565
|
+
sqs_values["policy"] = json_dumps(sqs_policy)
|
|
3566
3566
|
|
|
3567
3567
|
kms_encryption = common_values.get("kms_encryption", False)
|
|
3568
3568
|
if kms_encryption:
|
|
@@ -3598,7 +3598,7 @@ class TerrascriptClient:
|
|
|
3598
3598
|
},
|
|
3599
3599
|
],
|
|
3600
3600
|
}
|
|
3601
|
-
kms_values["policy"] =
|
|
3601
|
+
kms_values["policy"] = json_dumps(kms_policy)
|
|
3602
3602
|
if provider:
|
|
3603
3603
|
kms_values["provider"] = provider
|
|
3604
3604
|
|
|
@@ -3696,7 +3696,7 @@ class TerrascriptClient:
|
|
|
3696
3696
|
"Resource": [sqs_values["kms_master_key_id"]],
|
|
3697
3697
|
}
|
|
3698
3698
|
policy["Statement"].append(kms_statement)
|
|
3699
|
-
values_policy["policy"] =
|
|
3699
|
+
values_policy["policy"] = json_dumps(policy)
|
|
3700
3700
|
policy_tf_resource = aws_iam_policy(sqs_identifier, **values_policy)
|
|
3701
3701
|
tf_resources.append(policy_tf_resource)
|
|
3702
3702
|
|
|
@@ -3767,7 +3767,7 @@ class TerrascriptClient:
|
|
|
3767
3767
|
role_identifier = f"{identifier}-lambda-execution-role"
|
|
3768
3768
|
role_values = {
|
|
3769
3769
|
"name": role_identifier,
|
|
3770
|
-
"assume_role_policy":
|
|
3770
|
+
"assume_role_policy": json_dumps(assume_role_policy),
|
|
3771
3771
|
}
|
|
3772
3772
|
|
|
3773
3773
|
role_tf_resource = aws_iam_role(role_identifier, **role_values)
|
|
@@ -3799,7 +3799,7 @@ class TerrascriptClient:
|
|
|
3799
3799
|
|
|
3800
3800
|
policy_values = {
|
|
3801
3801
|
"role": "${" + role_tf_resource.id + "}",
|
|
3802
|
-
"policy":
|
|
3802
|
+
"policy": json_dumps(policy),
|
|
3803
3803
|
}
|
|
3804
3804
|
policy_tf_resource = aws_iam_role_policy(policy_identifier, **policy_values)
|
|
3805
3805
|
tf_resources.append(policy_tf_resource)
|
|
@@ -3927,7 +3927,7 @@ class TerrascriptClient:
|
|
|
3927
3927
|
}
|
|
3928
3928
|
values = {
|
|
3929
3929
|
"name": identifier,
|
|
3930
|
-
"policy":
|
|
3930
|
+
"policy": json_dumps(policy),
|
|
3931
3931
|
"depends_on": self.get_dependencies([user_tf_resource]),
|
|
3932
3932
|
}
|
|
3933
3933
|
|
|
@@ -4024,6 +4024,22 @@ class TerrascriptClient:
|
|
|
4024
4024
|
kinesis_tf_resource = aws_kinesis_stream(identifier, **kinesis_values)
|
|
4025
4025
|
tf_resources.append(kinesis_tf_resource)
|
|
4026
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
|
+
|
|
4027
4043
|
es_identifier = common_values.get("es_identifier", None)
|
|
4028
4044
|
if es_identifier:
|
|
4029
4045
|
es_resource = self._find_resource_spec(
|
|
@@ -4048,7 +4064,7 @@ class TerrascriptClient:
|
|
|
4048
4064
|
role_identifier = f"{identifier}-lambda-execution-role"
|
|
4049
4065
|
role_values = {
|
|
4050
4066
|
"name": role_identifier,
|
|
4051
|
-
"assume_role_policy":
|
|
4067
|
+
"assume_role_policy": json_dumps(assume_role_policy),
|
|
4052
4068
|
"tags": tags,
|
|
4053
4069
|
}
|
|
4054
4070
|
|
|
@@ -4085,7 +4101,7 @@ class TerrascriptClient:
|
|
|
4085
4101
|
policy_tf_resource = aws_iam_policy(
|
|
4086
4102
|
policy_identifier,
|
|
4087
4103
|
name=policy_identifier,
|
|
4088
|
-
policy=
|
|
4104
|
+
policy=json_dumps(policy),
|
|
4089
4105
|
tags=tags,
|
|
4090
4106
|
)
|
|
4091
4107
|
tf_resources.append(policy_tf_resource)
|
|
@@ -4300,7 +4316,7 @@ class TerrascriptClient:
|
|
|
4300
4316
|
# iam user policy
|
|
4301
4317
|
values_policy: dict[str, Any] = {
|
|
4302
4318
|
"name": identifier,
|
|
4303
|
-
"policy":
|
|
4319
|
+
"policy": json_dumps(policy),
|
|
4304
4320
|
"depends_on": self.get_dependencies([user_tf_resource]),
|
|
4305
4321
|
}
|
|
4306
4322
|
|
|
@@ -4418,10 +4434,7 @@ class TerrascriptClient:
|
|
|
4418
4434
|
|
|
4419
4435
|
:return: key is AWS account name and value is terraform configuration
|
|
4420
4436
|
"""
|
|
4421
|
-
return {
|
|
4422
|
-
name: json.dumps(ts, indent=2, sort_keys=True)
|
|
4423
|
-
for name, ts in self.tss.items()
|
|
4424
|
-
}
|
|
4437
|
+
return {name: json_dumps(ts, indent=2) for name, ts in self.tss.items()}
|
|
4425
4438
|
|
|
4426
4439
|
def init_values(
|
|
4427
4440
|
self, spec: ExternalResourceSpec, init_tags: bool = True
|
|
@@ -4533,7 +4546,7 @@ class TerrascriptClient:
|
|
|
4533
4546
|
output_name = output_format.format(
|
|
4534
4547
|
spec.output_prefix, self.integration_prefix, "annotations"
|
|
4535
4548
|
)
|
|
4536
|
-
anno_json =
|
|
4549
|
+
anno_json = json_dumps(spec.annotations()).encode("utf-8")
|
|
4537
4550
|
output_value = base64.b64encode(anno_json).decode()
|
|
4538
4551
|
tf_resources.append(Output(output_name, value=output_value))
|
|
4539
4552
|
|
|
@@ -4673,7 +4686,7 @@ class TerrascriptClient:
|
|
|
4673
4686
|
}
|
|
4674
4687
|
log_groups_policy_values = {
|
|
4675
4688
|
"policy_name": "es-log-publishing-permissions",
|
|
4676
|
-
"policy_document":
|
|
4689
|
+
"policy_document": json_dumps(log_groups_policy),
|
|
4677
4690
|
}
|
|
4678
4691
|
resource_policy = aws_cloudwatch_log_resource_policy(
|
|
4679
4692
|
"es_log_publishing_resource_policy",
|
|
@@ -5005,7 +5018,7 @@ class TerrascriptClient:
|
|
|
5005
5018
|
}
|
|
5006
5019
|
],
|
|
5007
5020
|
}
|
|
5008
|
-
es_values["access_policies"] =
|
|
5021
|
+
es_values["access_policies"] = json_dumps(access_policies)
|
|
5009
5022
|
|
|
5010
5023
|
region = values.get("region") or self.default_regions.get(account)
|
|
5011
5024
|
assert region # make mypy happy
|
|
@@ -5061,7 +5074,7 @@ class TerrascriptClient:
|
|
|
5061
5074
|
|
|
5062
5075
|
version_values = {
|
|
5063
5076
|
"secret_id": "${" + aws_secret_resource.id + "}",
|
|
5064
|
-
"secret_string":
|
|
5077
|
+
"secret_string": json_dumps(master_user),
|
|
5065
5078
|
}
|
|
5066
5079
|
if provider:
|
|
5067
5080
|
version_values["provider"] = provider
|
|
@@ -5088,7 +5101,7 @@ class TerrascriptClient:
|
|
|
5088
5101
|
iam_policy_resource = aws_iam_policy(
|
|
5089
5102
|
secret_identifier,
|
|
5090
5103
|
name=f"{identifier}-secretsmanager-policy",
|
|
5091
|
-
policy=
|
|
5104
|
+
policy=json_dumps(policy),
|
|
5092
5105
|
tags=tags,
|
|
5093
5106
|
)
|
|
5094
5107
|
tf_resources.append(iam_policy_resource)
|
|
@@ -5500,7 +5513,7 @@ class TerrascriptClient:
|
|
|
5500
5513
|
lb_access_logs_s3_bucket_policy_values = {
|
|
5501
5514
|
"provider": provider,
|
|
5502
5515
|
"bucket": f"${{{lb_access_logs_s3_bucket_tf_resource.id}}}",
|
|
5503
|
-
"policy":
|
|
5516
|
+
"policy": json_dumps(policy),
|
|
5504
5517
|
}
|
|
5505
5518
|
lb_access_logs_s3_bucket_policy_tf_resource = aws_s3_bucket_policy(
|
|
5506
5519
|
policy_identifier, **lb_access_logs_s3_bucket_policy_values
|
|
@@ -5813,9 +5826,13 @@ class TerrascriptClient:
|
|
|
5813
5826
|
assert secret # make mypy happy
|
|
5814
5827
|
secret_data = self.secret_reader.read_all(secret)
|
|
5815
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
|
+
|
|
5816
5833
|
version_values: dict[str, Any] = {
|
|
5817
5834
|
"secret_id": "${" + aws_secret_resource.id + "}",
|
|
5818
|
-
"secret_string":
|
|
5835
|
+
"secret_string": json_dumps(secret_data),
|
|
5819
5836
|
}
|
|
5820
5837
|
|
|
5821
5838
|
if self._multiregion_account(account):
|
|
@@ -5836,6 +5853,66 @@ class TerrascriptClient:
|
|
|
5836
5853
|
|
|
5837
5854
|
self.add_resources(account, tf_resources)
|
|
5838
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
|
+
|
|
5839
5916
|
def get_commit_sha(self, repo_info: Mapping) -> str:
|
|
5840
5917
|
url = repo_info["url"]
|
|
5841
5918
|
ref = repo_info["ref"]
|
|
@@ -5854,7 +5931,8 @@ class TerrascriptClient:
|
|
|
5854
5931
|
return commit.sha
|
|
5855
5932
|
case "gitlab":
|
|
5856
5933
|
gitlab = self.init_gitlab()
|
|
5857
|
-
project
|
|
5934
|
+
if not (project := gitlab.get_project(url)):
|
|
5935
|
+
raise ValueError(f"could not find gitlab project for url {url}")
|
|
5858
5936
|
commits = project.commits.list(ref_name=ref, per_page=1, page=1)
|
|
5859
5937
|
return commits[0].id
|
|
5860
5938
|
case _:
|
|
@@ -6135,7 +6213,7 @@ class TerrascriptClient:
|
|
|
6135
6213
|
lambda_iam_role_resource = aws_iam_role(
|
|
6136
6214
|
"lambda_role",
|
|
6137
6215
|
name=f"ocm-{identifier}-cognito-lambda-role",
|
|
6138
|
-
assume_role_policy=
|
|
6216
|
+
assume_role_policy=json_dumps(lambda_role_policy),
|
|
6139
6217
|
managed_policy_arns=[lambda_managed_policy_arn],
|
|
6140
6218
|
force_detach_policies=False,
|
|
6141
6219
|
max_session_duration=3600,
|
|
@@ -6810,7 +6888,7 @@ class TerrascriptClient:
|
|
|
6810
6888
|
)
|
|
6811
6889
|
tf_resources.append(api_gateway_stage_resource)
|
|
6812
6890
|
|
|
6813
|
-
rest_api_policy =
|
|
6891
|
+
rest_api_policy = json_dumps({
|
|
6814
6892
|
"Version": "2012-10-17",
|
|
6815
6893
|
"Statement": [
|
|
6816
6894
|
{
|
|
@@ -6914,7 +6992,7 @@ class TerrascriptClient:
|
|
|
6914
6992
|
},
|
|
6915
6993
|
],
|
|
6916
6994
|
}
|
|
6917
|
-
cloudwatch_assume_role_policy =
|
|
6995
|
+
cloudwatch_assume_role_policy = json_dumps(policy)
|
|
6918
6996
|
|
|
6919
6997
|
cloudwatch_iam_role_resource = aws_iam_role(
|
|
6920
6998
|
"cloudwatch_assume_role",
|
|
@@ -6942,7 +7020,7 @@ class TerrascriptClient:
|
|
|
6942
7020
|
],
|
|
6943
7021
|
}
|
|
6944
7022
|
|
|
6945
|
-
cloudwatch_iam_policy_document =
|
|
7023
|
+
cloudwatch_iam_policy_document = json_dumps(policy)
|
|
6946
7024
|
|
|
6947
7025
|
cloudwatch_iam_policy_resource = aws_iam_policy(
|
|
6948
7026
|
"cloudwatch",
|
|
@@ -7187,7 +7265,7 @@ class TerrascriptClient:
|
|
|
7187
7265
|
|
|
7188
7266
|
version_values = {
|
|
7189
7267
|
"secret_id": "${" + secret_resource.arn + "}",
|
|
7190
|
-
"secret_string":
|
|
7268
|
+
"secret_string": json_dumps(secret),
|
|
7191
7269
|
}
|
|
7192
7270
|
version_resource = aws_secretsmanager_secret_version(
|
|
7193
7271
|
secret_identifier, **version_values
|
|
@@ -7196,7 +7274,7 @@ class TerrascriptClient:
|
|
|
7196
7274
|
|
|
7197
7275
|
secret_policy_values = {
|
|
7198
7276
|
"secret_arn": "${" + secret_resource.arn + "}",
|
|
7199
|
-
"policy":
|
|
7277
|
+
"policy": json_dumps({
|
|
7200
7278
|
"Version": "2012-10-17",
|
|
7201
7279
|
"Statement": [
|
|
7202
7280
|
{
|