qontract-reconcile 0.10.2.dev299__py3-none-any.whl → 0.10.2.dev430__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {qontract_reconcile-0.10.2.dev299.dist-info → qontract_reconcile-0.10.2.dev430.dist-info}/METADATA +13 -12
- {qontract_reconcile-0.10.2.dev299.dist-info → qontract_reconcile-0.10.2.dev430.dist-info}/RECORD +399 -394
- reconcile/acs_rbac.py +2 -2
- reconcile/aus/advanced_upgrade_service.py +18 -12
- reconcile/aus/base.py +134 -32
- reconcile/aus/cluster_version_data.py +15 -5
- reconcile/aus/models.py +3 -1
- reconcile/aus/ocm_addons_upgrade_scheduler_org.py +1 -0
- reconcile/aus/ocm_upgrade_scheduler.py +8 -1
- reconcile/aus/ocm_upgrade_scheduler_org.py +20 -5
- reconcile/aus/version_gates/sts_version_gate_handler.py +54 -1
- reconcile/automated_actions/config/integration.py +16 -4
- reconcile/aws_account_manager/integration.py +8 -8
- reconcile/aws_account_manager/reconciler.py +3 -3
- reconcile/aws_ami_cleanup/integration.py +8 -12
- reconcile/aws_ami_share.py +69 -62
- reconcile/aws_cloudwatch_log_retention/integration.py +155 -126
- reconcile/aws_ecr_image_pull_secrets.py +4 -4
- reconcile/aws_iam_keys.py +1 -0
- reconcile/aws_saml_idp/integration.py +12 -4
- reconcile/aws_saml_roles/integration.py +32 -25
- reconcile/aws_version_sync/integration.py +125 -84
- reconcile/change_owners/bundle.py +3 -3
- reconcile/change_owners/change_log_tracking.py +3 -2
- reconcile/change_owners/change_owners.py +1 -1
- reconcile/change_owners/diff.py +2 -4
- reconcile/checkpoint.py +12 -4
- reconcile/cli.py +111 -18
- reconcile/cluster_deployment_mapper.py +2 -3
- reconcile/dashdotdb_dora.py +5 -12
- reconcile/dashdotdb_slo.py +1 -1
- reconcile/database_access_manager.py +125 -121
- reconcile/deadmanssnitch.py +1 -5
- reconcile/dynatrace_token_provider/integration.py +1 -1
- reconcile/endpoints_discovery/integration.py +4 -1
- reconcile/endpoints_discovery/merge_request.py +1 -1
- reconcile/endpoints_discovery/merge_request_manager.py +9 -11
- reconcile/external_resources/factories.py +5 -12
- reconcile/external_resources/integration.py +1 -1
- reconcile/external_resources/manager.py +8 -5
- reconcile/external_resources/meta.py +0 -1
- reconcile/external_resources/metrics.py +1 -1
- reconcile/external_resources/model.py +20 -20
- reconcile/external_resources/reconciler.py +7 -4
- reconcile/external_resources/secrets_sync.py +8 -11
- reconcile/external_resources/state.py +26 -16
- reconcile/fleet_labeler/integration.py +1 -1
- reconcile/gabi_authorized_users.py +8 -5
- reconcile/gcp_image_mirror.py +2 -2
- reconcile/github_org.py +1 -1
- reconcile/github_owners.py +4 -0
- reconcile/gitlab_housekeeping.py +13 -15
- reconcile/gitlab_members.py +6 -12
- reconcile/gitlab_mr_sqs_consumer.py +2 -2
- reconcile/gitlab_owners.py +15 -11
- reconcile/gitlab_permissions.py +8 -12
- reconcile/glitchtip_project_alerts/integration.py +3 -1
- reconcile/gql_definitions/acs/acs_instances.py +10 -10
- reconcile/gql_definitions/acs/acs_policies.py +5 -5
- reconcile/gql_definitions/acs/acs_rbac.py +6 -6
- reconcile/gql_definitions/advanced_upgrade_service/aus_clusters.py +32 -32
- reconcile/gql_definitions/advanced_upgrade_service/aus_organization.py +26 -26
- reconcile/gql_definitions/app_interface_metrics_exporter/onboarding_status.py +6 -7
- reconcile/gql_definitions/app_sre_tekton_access_revalidation/roles.py +5 -5
- reconcile/gql_definitions/app_sre_tekton_access_revalidation/users.py +5 -5
- reconcile/gql_definitions/automated_actions/instance.py +51 -12
- reconcile/gql_definitions/aws_account_manager/aws_accounts.py +11 -11
- reconcile/gql_definitions/aws_ami_cleanup/aws_accounts.py +20 -10
- reconcile/gql_definitions/aws_cloudwatch_log_retention/aws_accounts.py +28 -68
- reconcile/gql_definitions/aws_saml_idp/aws_accounts.py +20 -10
- reconcile/gql_definitions/aws_saml_roles/aws_accounts.py +20 -10
- reconcile/gql_definitions/aws_saml_roles/roles.py +5 -5
- reconcile/gql_definitions/aws_version_sync/clusters.py +10 -10
- reconcile/gql_definitions/aws_version_sync/namespaces.py +5 -5
- reconcile/gql_definitions/change_owners/queries/change_types.py +5 -5
- reconcile/gql_definitions/change_owners/queries/self_service_roles.py +9 -9
- reconcile/gql_definitions/cluster_auth_rhidp/clusters.py +18 -18
- reconcile/gql_definitions/common/alerting_services_settings.py +9 -9
- reconcile/gql_definitions/common/app_code_component_repos.py +5 -5
- reconcile/gql_definitions/common/app_interface_custom_messages.py +5 -5
- reconcile/gql_definitions/common/app_interface_dms_settings.py +5 -5
- reconcile/gql_definitions/common/app_interface_repo_settings.py +5 -5
- reconcile/gql_definitions/common/app_interface_roles.py +120 -0
- reconcile/gql_definitions/common/app_interface_state_settings.py +10 -10
- reconcile/gql_definitions/common/app_interface_vault_settings.py +5 -5
- reconcile/gql_definitions/common/app_quay_repos_escalation_policies.py +5 -5
- reconcile/gql_definitions/common/apps.py +5 -5
- reconcile/gql_definitions/common/aws_vpc_requests.py +23 -10
- reconcile/gql_definitions/common/aws_vpcs.py +11 -11
- reconcile/gql_definitions/common/clusters.py +37 -35
- reconcile/gql_definitions/common/clusters_minimal.py +14 -14
- reconcile/gql_definitions/common/clusters_with_dms.py +6 -6
- reconcile/gql_definitions/common/clusters_with_peering.py +29 -30
- reconcile/gql_definitions/common/github_orgs.py +10 -10
- reconcile/gql_definitions/common/jira_settings.py +10 -10
- reconcile/gql_definitions/common/jiralert_settings.py +5 -5
- reconcile/gql_definitions/common/ldap_settings.py +5 -5
- reconcile/gql_definitions/common/namespaces.py +42 -44
- reconcile/gql_definitions/common/namespaces_minimal.py +15 -13
- reconcile/gql_definitions/common/ocm_env_telemeter.py +12 -12
- reconcile/gql_definitions/common/ocm_environments.py +19 -19
- reconcile/gql_definitions/common/pagerduty_instances.py +9 -9
- reconcile/gql_definitions/common/pgp_reencryption_settings.py +6 -6
- reconcile/gql_definitions/common/pipeline_providers.py +29 -29
- reconcile/gql_definitions/common/quay_instances.py +5 -5
- reconcile/gql_definitions/common/quay_orgs.py +5 -5
- reconcile/gql_definitions/common/reserved_networks.py +5 -5
- reconcile/gql_definitions/common/rhcs_provider_settings.py +5 -5
- reconcile/gql_definitions/common/saas_files.py +44 -44
- reconcile/gql_definitions/common/saas_target_namespaces.py +10 -10
- reconcile/gql_definitions/common/saasherder_settings.py +5 -5
- reconcile/gql_definitions/common/slack_workspaces.py +5 -5
- reconcile/gql_definitions/common/smtp_client_settings.py +19 -19
- reconcile/gql_definitions/common/state_aws_account.py +7 -8
- reconcile/gql_definitions/common/users.py +5 -5
- reconcile/gql_definitions/common/users_with_paths.py +5 -5
- reconcile/gql_definitions/cost_report/app_names.py +5 -5
- reconcile/gql_definitions/cost_report/cost_namespaces.py +5 -5
- reconcile/gql_definitions/cost_report/settings.py +9 -9
- reconcile/gql_definitions/dashdotdb_slo/slo_documents_query.py +43 -43
- reconcile/gql_definitions/dynatrace_token_provider/dynatrace_bootstrap_tokens.py +10 -10
- reconcile/gql_definitions/dynatrace_token_provider/token_specs.py +5 -5
- reconcile/gql_definitions/email_sender/apps.py +5 -5
- reconcile/gql_definitions/email_sender/emails.py +8 -8
- reconcile/gql_definitions/email_sender/users.py +6 -6
- reconcile/gql_definitions/endpoints_discovery/apps.py +10 -10
- reconcile/gql_definitions/external_resources/aws_accounts.py +9 -9
- reconcile/gql_definitions/external_resources/external_resources_modules.py +23 -23
- reconcile/gql_definitions/external_resources/external_resources_namespaces.py +492 -410
- reconcile/gql_definitions/external_resources/external_resources_settings.py +28 -26
- reconcile/gql_definitions/external_resources/fragments/external_resources_module_overrides.py +5 -5
- reconcile/gql_definitions/fleet_labeler/fleet_labels.py +40 -40
- reconcile/gql_definitions/fragments/aus_organization.py +5 -5
- reconcile/gql_definitions/fragments/aws_account_common.py +7 -5
- reconcile/gql_definitions/fragments/aws_account_managed.py +5 -5
- reconcile/gql_definitions/fragments/aws_account_sso.py +5 -5
- reconcile/gql_definitions/fragments/aws_infra_management_account.py +5 -5
- reconcile/gql_definitions/fragments/{aws_vpc_request_subnet.py → aws_organization.py} +12 -8
- reconcile/gql_definitions/fragments/aws_vpc.py +5 -5
- reconcile/gql_definitions/fragments/aws_vpc_request.py +10 -5
- reconcile/gql_definitions/fragments/container_image_mirror.py +5 -5
- reconcile/gql_definitions/fragments/deploy_resources.py +5 -5
- reconcile/gql_definitions/fragments/disable.py +5 -5
- reconcile/gql_definitions/fragments/email_service.py +5 -5
- reconcile/gql_definitions/fragments/email_user.py +5 -5
- reconcile/gql_definitions/fragments/jumphost_common_fields.py +5 -5
- reconcile/gql_definitions/fragments/membership_source.py +5 -5
- reconcile/gql_definitions/fragments/minimal_ocm_organization.py +5 -5
- reconcile/gql_definitions/fragments/oc_connection_cluster.py +5 -5
- reconcile/gql_definitions/fragments/ocm_environment.py +5 -5
- reconcile/gql_definitions/fragments/pipeline_provider_retention.py +5 -5
- reconcile/gql_definitions/fragments/prometheus_instance.py +5 -5
- reconcile/gql_definitions/fragments/resource_limits_requirements.py +5 -5
- reconcile/gql_definitions/fragments/resource_requests_requirements.py +5 -5
- reconcile/gql_definitions/fragments/resource_values.py +5 -5
- reconcile/gql_definitions/fragments/saas_slo_document.py +5 -5
- reconcile/gql_definitions/fragments/saas_target_namespace.py +5 -5
- reconcile/gql_definitions/fragments/serviceaccount_token.py +5 -5
- reconcile/gql_definitions/fragments/terraform_state.py +5 -5
- reconcile/gql_definitions/fragments/upgrade_policy.py +5 -5
- reconcile/gql_definitions/fragments/user.py +5 -5
- reconcile/gql_definitions/fragments/vault_secret.py +5 -5
- reconcile/gql_definitions/gcp/gcp_docker_repos.py +9 -9
- reconcile/gql_definitions/gcp/gcp_projects.py +9 -9
- reconcile/gql_definitions/gitlab_members/gitlab_instances.py +9 -9
- reconcile/gql_definitions/gitlab_members/permissions.py +9 -9
- reconcile/gql_definitions/glitchtip/glitchtip_instance.py +9 -9
- reconcile/gql_definitions/glitchtip/glitchtip_project.py +11 -11
- reconcile/gql_definitions/glitchtip_project_alerts/glitchtip_project.py +9 -9
- reconcile/gql_definitions/integrations/integrations.py +48 -51
- reconcile/gql_definitions/introspection.json +3050 -1393
- reconcile/gql_definitions/jenkins_configs/jenkins_configs.py +11 -11
- reconcile/gql_definitions/jenkins_configs/jenkins_instances.py +10 -10
- reconcile/gql_definitions/jira/jira_servers.py +5 -5
- reconcile/gql_definitions/jira_permissions_validator/jira_boards_for_permissions_validator.py +14 -10
- reconcile/gql_definitions/jumphosts/jumphosts.py +13 -13
- reconcile/gql_definitions/ldap_groups/roles.py +5 -5
- reconcile/gql_definitions/ldap_groups/settings.py +9 -9
- reconcile/gql_definitions/maintenance/maintenances.py +5 -5
- reconcile/gql_definitions/membershipsources/roles.py +5 -5
- reconcile/gql_definitions/ocm_labels/clusters.py +18 -19
- reconcile/gql_definitions/ocm_labels/organizations.py +5 -5
- reconcile/gql_definitions/openshift_cluster_bots/clusters.py +22 -22
- reconcile/gql_definitions/openshift_groups/managed_groups.py +5 -5
- reconcile/gql_definitions/openshift_groups/managed_roles.py +6 -6
- reconcile/gql_definitions/openshift_serviceaccount_tokens/tokens.py +10 -10
- reconcile/gql_definitions/quay_membership/quay_membership.py +6 -6
- reconcile/gql_definitions/rhcs/certs.py +33 -87
- reconcile/gql_definitions/rhcs/openshift_resource_rhcs_cert.py +43 -0
- reconcile/gql_definitions/rhidp/organizations.py +18 -18
- reconcile/gql_definitions/service_dependencies/jenkins_instance_fragment.py +5 -5
- reconcile/gql_definitions/service_dependencies/service_dependencies.py +8 -8
- reconcile/gql_definitions/sharding/aws_accounts.py +10 -10
- reconcile/gql_definitions/sharding/ocm_organization.py +8 -8
- reconcile/gql_definitions/skupper_network/site_controller_template.py +5 -5
- reconcile/gql_definitions/skupper_network/skupper_networks.py +10 -10
- reconcile/gql_definitions/slack_usergroups/clusters.py +5 -5
- reconcile/gql_definitions/slack_usergroups/permissions.py +9 -9
- reconcile/gql_definitions/slack_usergroups/users.py +5 -5
- reconcile/gql_definitions/slo_documents/slo_documents.py +5 -5
- reconcile/gql_definitions/status_board/status_board.py +6 -7
- reconcile/gql_definitions/statuspage/statuspages.py +9 -9
- reconcile/gql_definitions/templating/template_collection.py +5 -5
- reconcile/gql_definitions/templating/templates.py +5 -5
- reconcile/gql_definitions/terraform_cloudflare_dns/app_interface_cloudflare_dns_settings.py +6 -6
- reconcile/gql_definitions/terraform_cloudflare_dns/terraform_cloudflare_zones.py +11 -11
- reconcile/gql_definitions/terraform_cloudflare_resources/terraform_cloudflare_accounts.py +11 -11
- reconcile/gql_definitions/terraform_cloudflare_resources/terraform_cloudflare_resources.py +20 -25
- reconcile/gql_definitions/terraform_cloudflare_users/app_interface_setting_cloudflare_and_vault.py +6 -6
- reconcile/gql_definitions/terraform_cloudflare_users/terraform_cloudflare_roles.py +12 -12
- reconcile/gql_definitions/terraform_init/aws_accounts.py +23 -9
- reconcile/gql_definitions/terraform_repo/terraform_repo.py +9 -9
- reconcile/gql_definitions/terraform_resources/database_access_manager.py +5 -5
- reconcile/gql_definitions/terraform_resources/terraform_resources_namespaces.py +448 -402
- reconcile/gql_definitions/terraform_tgw_attachments/aws_accounts.py +23 -17
- reconcile/gql_definitions/unleash_feature_toggles/feature_toggles.py +9 -9
- reconcile/gql_definitions/vault_instances/vault_instances.py +61 -61
- reconcile/gql_definitions/vault_policies/vault_policies.py +11 -11
- reconcile/gql_definitions/vpc_peerings_validator/vpc_peerings_validator.py +8 -8
- reconcile/gql_definitions/vpc_peerings_validator/vpc_peerings_validator_peered_cluster_fragment.py +5 -5
- reconcile/integrations_manager.py +3 -3
- reconcile/jenkins_job_builder.py +1 -1
- reconcile/jenkins_worker_fleets.py +80 -11
- reconcile/jira_permissions_validator.py +237 -122
- reconcile/ldap_groups/integration.py +1 -1
- reconcile/ocm/types.py +35 -56
- reconcile/ocm_aws_infrastructure_access.py +1 -1
- reconcile/ocm_clusters.py +4 -4
- reconcile/ocm_labels/integration.py +3 -2
- reconcile/ocm_machine_pools.py +33 -27
- reconcile/openshift_base.py +122 -10
- reconcile/openshift_cluster_bots.py +5 -5
- reconcile/openshift_groups.py +5 -0
- reconcile/openshift_limitranges.py +1 -1
- reconcile/openshift_namespace_labels.py +1 -1
- reconcile/openshift_namespaces.py +97 -101
- reconcile/openshift_resources_base.py +10 -5
- reconcile/openshift_rhcs_certs.py +77 -40
- reconcile/openshift_rolebindings.py +230 -130
- reconcile/openshift_saas_deploy.py +6 -7
- reconcile/openshift_saas_deploy_change_tester.py +9 -7
- reconcile/openshift_saas_deploy_trigger_cleaner.py +3 -5
- reconcile/openshift_serviceaccount_tokens.py +8 -7
- reconcile/openshift_tekton_resources.py +1 -1
- reconcile/openshift_upgrade_watcher.py +4 -4
- reconcile/openshift_users.py +5 -3
- reconcile/oum/labelset.py +5 -3
- reconcile/oum/models.py +1 -4
- reconcile/oum/providers.py +1 -1
- reconcile/prometheus_rules_tester/integration.py +4 -4
- reconcile/quay_mirror.py +1 -1
- reconcile/queries.py +131 -0
- reconcile/requests_sender.py +8 -3
- reconcile/resource_scraper.py +1 -5
- reconcile/rhidp/common.py +5 -5
- reconcile/rhidp/sso_client/base.py +19 -10
- reconcile/saas_auto_promotions_manager/merge_request_manager/renderer.py +1 -1
- reconcile/saas_auto_promotions_manager/subscriber.py +4 -3
- reconcile/sendgrid_teammates.py +20 -9
- reconcile/skupper_network/integration.py +2 -2
- reconcile/slack_usergroups.py +35 -14
- reconcile/sql_query.py +1 -0
- reconcile/status.py +2 -2
- reconcile/status_board.py +6 -6
- reconcile/statuspage/atlassian.py +7 -7
- reconcile/statuspage/integrations/maintenances.py +4 -3
- reconcile/statuspage/page.py +4 -9
- reconcile/statuspage/status.py +5 -8
- reconcile/templates/rosa-classic-cluster-creation.sh.j2 +4 -0
- reconcile/templates/rosa-hcp-cluster-creation.sh.j2 +3 -0
- reconcile/templating/lib/merge_request_manager.py +2 -2
- reconcile/templating/lib/rendering.py +3 -3
- reconcile/templating/renderer.py +12 -13
- reconcile/terraform_aws_route53.py +18 -8
- reconcile/terraform_cloudflare_dns.py +3 -3
- reconcile/terraform_cloudflare_resources.py +12 -13
- reconcile/terraform_cloudflare_users.py +3 -2
- reconcile/terraform_init/integration.py +187 -23
- reconcile/terraform_repo.py +16 -12
- reconcile/terraform_resources.py +18 -10
- reconcile/terraform_tgw_attachments.py +27 -19
- reconcile/terraform_users.py +29 -21
- reconcile/terraform_vpc_peerings.py +16 -4
- reconcile/terraform_vpc_resources/integration.py +32 -2
- reconcile/typed_queries/app_interface_roles.py +10 -0
- reconcile/typed_queries/aws_account_tags.py +41 -0
- reconcile/typed_queries/cost_report/app_names.py +1 -1
- reconcile/typed_queries/cost_report/cost_namespaces.py +2 -2
- reconcile/typed_queries/saas_files.py +13 -13
- reconcile/typed_queries/status_board.py +2 -2
- reconcile/unleash_feature_toggles/integration.py +4 -2
- reconcile/utils/acs/base.py +6 -3
- reconcile/utils/acs/policies.py +2 -2
- reconcile/utils/aggregated_list.py +4 -3
- reconcile/utils/aws_api.py +51 -20
- reconcile/utils/aws_api_typed/api.py +38 -9
- reconcile/utils/aws_api_typed/cloudformation.py +149 -0
- reconcile/utils/aws_api_typed/logs.py +73 -0
- reconcile/utils/aws_api_typed/organization.py +4 -2
- reconcile/utils/binary.py +7 -12
- reconcile/utils/datetime_util.py +67 -0
- reconcile/utils/deadmanssnitch_api.py +1 -1
- reconcile/utils/differ.py +2 -3
- reconcile/utils/early_exit_cache.py +11 -12
- reconcile/utils/expiration.py +7 -3
- reconcile/utils/external_resource_spec.py +24 -1
- reconcile/utils/filtering.py +1 -1
- reconcile/utils/gitlab_api.py +7 -5
- reconcile/utils/glitchtip/client.py +6 -2
- reconcile/utils/glitchtip/models.py +25 -28
- reconcile/utils/gpg.py +5 -3
- reconcile/utils/gql.py +4 -7
- reconcile/utils/helm.py +2 -1
- reconcile/utils/helpers.py +1 -1
- reconcile/utils/imap_client.py +1 -1
- reconcile/utils/instrumented_wrappers.py +1 -1
- reconcile/utils/internal_groups/client.py +2 -2
- reconcile/utils/internal_groups/models.py +8 -17
- reconcile/utils/jenkins_api.py +24 -1
- reconcile/utils/jinja2/utils.py +6 -8
- reconcile/utils/jira_client.py +82 -63
- reconcile/utils/jjb_client.py +59 -43
- reconcile/utils/jobcontroller/controller.py +2 -2
- reconcile/utils/jobcontroller/models.py +17 -1
- reconcile/utils/json.py +74 -0
- reconcile/utils/ldap_client.py +4 -3
- reconcile/utils/lean_terraform_client.py +3 -1
- reconcile/utils/membershipsources/app_interface_resolver.py +4 -2
- reconcile/utils/membershipsources/models.py +16 -23
- reconcile/utils/membershipsources/resolver.py +4 -2
- reconcile/utils/merge_request_manager/merge_request_manager.py +4 -4
- reconcile/utils/merge_request_manager/parser.py +6 -6
- reconcile/utils/metrics.py +5 -5
- reconcile/utils/models.py +304 -82
- reconcile/utils/mr/__init__.py +3 -1
- reconcile/utils/mr/app_interface_reporter.py +6 -3
- reconcile/utils/mr/aws_access.py +1 -1
- reconcile/utils/mr/base.py +7 -13
- reconcile/utils/mr/clusters_updates.py +4 -2
- reconcile/utils/mr/notificator.py +3 -3
- reconcile/utils/mr/ocm_upgrade_scheduler_org_updates.py +4 -1
- reconcile/utils/mr/promote_qontract.py +28 -12
- reconcile/utils/mr/update_access_report_base.py +3 -4
- reconcile/utils/mr/user_maintenance.py +7 -6
- reconcile/utils/oc.py +445 -336
- reconcile/utils/oc_filters.py +3 -3
- reconcile/utils/ocm/addons.py +0 -1
- reconcile/utils/ocm/base.py +27 -20
- reconcile/utils/ocm/cluster_groups.py +1 -1
- reconcile/utils/ocm/identity_providers.py +2 -2
- reconcile/utils/ocm/labels.py +1 -1
- reconcile/utils/ocm/ocm.py +81 -71
- reconcile/utils/ocm/products.py +9 -3
- reconcile/utils/ocm/search_filters.py +3 -6
- reconcile/utils/ocm/service_log.py +4 -6
- reconcile/utils/ocm/sre_capability_labels.py +20 -13
- reconcile/utils/ocm_base_client.py +4 -4
- reconcile/utils/openshift_resource.py +83 -52
- reconcile/utils/openssl.py +2 -2
- reconcile/utils/output.py +3 -2
- reconcile/utils/pagerduty_api.py +10 -7
- reconcile/utils/promotion_state.py +6 -11
- reconcile/utils/raw_github_api.py +11 -8
- reconcile/utils/repo_owners.py +21 -29
- reconcile/utils/rhcsv2_certs.py +138 -35
- reconcile/utils/rosa/session.py +16 -0
- reconcile/utils/runtime/integration.py +2 -3
- reconcile/utils/runtime/meta.py +2 -1
- reconcile/utils/runtime/runner.py +2 -2
- reconcile/utils/saasherder/interfaces.py +13 -20
- reconcile/utils/saasherder/models.py +25 -21
- reconcile/utils/saasherder/saasherder.py +60 -32
- reconcile/utils/secret_reader.py +6 -6
- reconcile/utils/sharding.py +1 -1
- reconcile/utils/slack_api.py +26 -4
- reconcile/utils/sloth.py +224 -0
- reconcile/utils/sqs_gateway.py +16 -11
- reconcile/utils/state.py +2 -1
- reconcile/utils/structs.py +4 -4
- reconcile/utils/terraform_client.py +32 -29
- reconcile/utils/terrascript_aws_client.py +658 -480
- reconcile/utils/three_way_diff_strategy.py +1 -1
- reconcile/utils/throughput.py +1 -1
- reconcile/utils/unleash/server.py +2 -8
- reconcile/utils/vault.py +44 -41
- reconcile/utils/vcs.py +8 -8
- reconcile/vault_replication.py +119 -58
- reconcile/vpc_peerings_validator.py +2 -2
- tools/app_interface_reporter.py +4 -4
- tools/cli_commands/cost_report/cost_management_api.py +3 -3
- tools/cli_commands/cost_report/view.py +7 -6
- tools/cli_commands/erv2.py +1 -1
- tools/cli_commands/gpg_encrypt.py +4 -1
- tools/cli_commands/systems_and_tools.py +5 -1
- tools/qontract_cli.py +36 -21
- tools/sre_checkpoints/util.py +5 -3
- tools/template_validation.py +3 -1
- reconcile/gql_definitions/ocm_oidc_idp/__init__.py +0 -0
- reconcile/gql_definitions/ocm_subscription_labels/__init__.py +0 -0
- reconcile/jenkins/__init__.py +0 -0
- reconcile/jenkins/types.py +0 -77
- {qontract_reconcile-0.10.2.dev299.dist-info → qontract_reconcile-0.10.2.dev430.dist-info}/WHEEL +0 -0
- {qontract_reconcile-0.10.2.dev299.dist-info → qontract_reconcile-0.10.2.dev430.dist-info}/entry_points.txt +0 -0
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
# ruff: noqa: N801
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
2
4
|
import base64
|
|
3
5
|
import enum
|
|
4
6
|
import json
|
|
@@ -9,7 +11,6 @@ import re
|
|
|
9
11
|
import string
|
|
10
12
|
import tempfile
|
|
11
13
|
from collections import Counter
|
|
12
|
-
from collections.abc import Iterable, Mapping, MutableMapping
|
|
13
14
|
from dataclasses import dataclass, field
|
|
14
15
|
from ipaddress import (
|
|
15
16
|
ip_address,
|
|
@@ -18,7 +19,9 @@ from ipaddress import (
|
|
|
18
19
|
from json import JSONDecodeError
|
|
19
20
|
from threading import Lock
|
|
20
21
|
from typing import (
|
|
22
|
+
TYPE_CHECKING,
|
|
21
23
|
Any,
|
|
24
|
+
Self,
|
|
22
25
|
cast,
|
|
23
26
|
)
|
|
24
27
|
|
|
@@ -34,12 +37,14 @@ from terrascript import (
|
|
|
34
37
|
Backend,
|
|
35
38
|
Block,
|
|
36
39
|
Data,
|
|
40
|
+
Locals,
|
|
37
41
|
Module,
|
|
38
42
|
Output,
|
|
39
43
|
Provider,
|
|
40
44
|
Resource,
|
|
41
45
|
Terraform,
|
|
42
46
|
Terrascript,
|
|
47
|
+
Variable,
|
|
43
48
|
data,
|
|
44
49
|
provider,
|
|
45
50
|
)
|
|
@@ -143,12 +148,10 @@ import reconcile.utils.aws_helper as awsh
|
|
|
143
148
|
from reconcile import queries
|
|
144
149
|
from reconcile.cli import TERRAFORM_VERSION
|
|
145
150
|
from reconcile.github_org import get_default_config
|
|
146
|
-
from reconcile.gql_definitions.fragments.aws_vpc_request import (
|
|
147
|
-
VPCRequest,
|
|
148
|
-
)
|
|
149
151
|
from reconcile.gql_definitions.terraform_resources.terraform_resources_namespaces import (
|
|
150
152
|
NamespaceTerraformResourceLifecycleV1,
|
|
151
153
|
)
|
|
154
|
+
from reconcile.typed_queries.aws_account_tags import get_aws_account_tags
|
|
152
155
|
from reconcile.utils import gql
|
|
153
156
|
from reconcile.utils.aws_api import (
|
|
154
157
|
AmiTag,
|
|
@@ -168,10 +171,6 @@ from reconcile.utils.exceptions import (
|
|
|
168
171
|
FetchResourceError,
|
|
169
172
|
PrintToFileInGitRepositoryError,
|
|
170
173
|
)
|
|
171
|
-
from reconcile.utils.external_resource_spec import (
|
|
172
|
-
ExternalResourceSpec,
|
|
173
|
-
ExternalResourceSpecInventory,
|
|
174
|
-
)
|
|
175
174
|
from reconcile.utils.external_resources import (
|
|
176
175
|
PROVIDER_AWS,
|
|
177
176
|
get_external_resource_specs,
|
|
@@ -179,8 +178,11 @@ from reconcile.utils.external_resources import (
|
|
|
179
178
|
from reconcile.utils.git import is_file_in_git_repo
|
|
180
179
|
from reconcile.utils.gitlab_api import GitLabApi
|
|
181
180
|
from reconcile.utils.jenkins_api import JenkinsApi
|
|
182
|
-
from reconcile.utils.jinja2.utils import
|
|
183
|
-
|
|
181
|
+
from reconcile.utils.jinja2.utils import (
|
|
182
|
+
process_extracurlyjinja2_template,
|
|
183
|
+
process_jinja2_template,
|
|
184
|
+
)
|
|
185
|
+
from reconcile.utils.json import json_dumps
|
|
184
186
|
from reconcile.utils.password_validator import (
|
|
185
187
|
PasswordPolicy,
|
|
186
188
|
PasswordValidator,
|
|
@@ -189,6 +191,25 @@ from reconcile.utils.secret_reader import SecretReader, SecretReaderBase
|
|
|
189
191
|
from reconcile.utils.terraform import safe_resource_id
|
|
190
192
|
from reconcile.utils.vcs import VCS
|
|
191
193
|
|
|
194
|
+
if TYPE_CHECKING:
|
|
195
|
+
from collections.abc import Iterable, Mapping, MutableMapping
|
|
196
|
+
|
|
197
|
+
from reconcile.gql_definitions.fragments.aws_vpc_request import (
|
|
198
|
+
VPCRequest,
|
|
199
|
+
)
|
|
200
|
+
from reconcile.terraform_tgw_attachments import DesiredStateItem
|
|
201
|
+
from reconcile.terraform_users import Role
|
|
202
|
+
from reconcile.utils.external_resource_spec import (
|
|
203
|
+
ExternalResourceSpec,
|
|
204
|
+
ExternalResourceSpecInventory,
|
|
205
|
+
)
|
|
206
|
+
from reconcile.utils.ocm import OCMMap
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
type TFResource = type[
|
|
210
|
+
Resource | Data | Module | Provider | Variable | Output | Locals | Terraform
|
|
211
|
+
]
|
|
212
|
+
|
|
192
213
|
GH_BASE_URL = os.environ.get("GITHUB_API", "https://api.github.com")
|
|
193
214
|
ROSA_AUTH_LOGTOES_RELEASE = "repos/app-sre/logs-to-elasticsearch-lambda/releases/latest"
|
|
194
215
|
ROSA_AUTH_KINESIS_TO_OS_RELEASE = (
|
|
@@ -250,6 +271,7 @@ VARIABLE_KEYS = [
|
|
|
250
271
|
"extra_tags",
|
|
251
272
|
"lifecycle",
|
|
252
273
|
"max_session_duration",
|
|
274
|
+
"secret_format",
|
|
253
275
|
]
|
|
254
276
|
|
|
255
277
|
EMAIL_REGEX = re.compile(r"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$")
|
|
@@ -265,15 +287,10 @@ SUPPORTED_ALB_LISTENER_RULE_CONDITION_TYPE_MAPPING = {
|
|
|
265
287
|
"host-header": "host_header",
|
|
266
288
|
"http-request-method": "http_request_method",
|
|
267
289
|
"path-pattern": "path_pattern",
|
|
290
|
+
"query-string": "query_string",
|
|
268
291
|
"source-ip": "source_ip",
|
|
269
292
|
}
|
|
270
293
|
|
|
271
|
-
DEFAULT_TAGS = {
|
|
272
|
-
"tags": {
|
|
273
|
-
"app": "app-sre-infra",
|
|
274
|
-
},
|
|
275
|
-
}
|
|
276
|
-
|
|
277
294
|
AWS_ELB_ACCOUNT_IDS = {
|
|
278
295
|
"us-east-1": "127311923021",
|
|
279
296
|
"us-east-2": "033677994240",
|
|
@@ -304,9 +321,12 @@ AWS_US_GOV_ELB_ACCOUNT_IDS = {
|
|
|
304
321
|
"us-gov-east-1": "190560391635",
|
|
305
322
|
}
|
|
306
323
|
|
|
324
|
+
VPC_REQUEST_DEFAULT_PRIVATE_SUBNET_TAGS = {"kubernetes.io/role/internal-elb": "1"}
|
|
325
|
+
VPC_REQUEST_DEFAULT_PUBLIC_SUBNET_TAGS = {"kubernetes.io/role/elb": "1"}
|
|
326
|
+
|
|
307
327
|
|
|
308
328
|
class OutputResourceNameNotUniqueError(Exception):
|
|
309
|
-
def __init__(self, namespace, duplicates):
|
|
329
|
+
def __init__(self, namespace: str | None, duplicates: Iterable[str]) -> None:
|
|
310
330
|
self.namespace, self.duplicates = namespace, duplicates
|
|
311
331
|
super().__init__(
|
|
312
332
|
str.format(
|
|
@@ -326,7 +346,7 @@ class StateInaccessibleError(Exception):
|
|
|
326
346
|
|
|
327
347
|
|
|
328
348
|
class UnknownProviderError(Exception):
|
|
329
|
-
def __init__(self, msg):
|
|
349
|
+
def __init__(self, msg: str) -> None:
|
|
330
350
|
super().__init__("unknown provider error: " + str(msg))
|
|
331
351
|
|
|
332
352
|
|
|
@@ -453,9 +473,10 @@ class TerrascriptClient:
|
|
|
453
473
|
integration: str,
|
|
454
474
|
integration_prefix: str,
|
|
455
475
|
thread_pool_size: int,
|
|
456
|
-
accounts: Iterable[
|
|
476
|
+
accounts: Iterable[MutableMapping[str, Any]],
|
|
477
|
+
default_tags: Mapping[str, str] | None,
|
|
457
478
|
settings: Mapping[str, Any] | None = None,
|
|
458
|
-
prefetch_resources_by_schemas:
|
|
479
|
+
prefetch_resources_by_schemas: Iterable[str] | None = None,
|
|
459
480
|
secret_reader: SecretReaderBase | None = None,
|
|
460
481
|
) -> None:
|
|
461
482
|
self.integration = integration
|
|
@@ -467,6 +488,7 @@ class TerrascriptClient:
|
|
|
467
488
|
else:
|
|
468
489
|
self.secret_reader = SecretReader(settings=settings)
|
|
469
490
|
self.configs: dict[str, dict] = {}
|
|
491
|
+
self.default_tags = default_tags or {"app": "app-sre-infra"}
|
|
470
492
|
self.populate_configs(filtered_accounts)
|
|
471
493
|
self.versions: dict[str, str] = {
|
|
472
494
|
a["name"]: a["providerVersion"] for a in filtered_accounts
|
|
@@ -487,7 +509,7 @@ class TerrascriptClient:
|
|
|
487
509
|
region=region,
|
|
488
510
|
alias=region,
|
|
489
511
|
skip_region_validation=True,
|
|
490
|
-
default_tags=
|
|
512
|
+
default_tags={"tags": config["tags"]},
|
|
491
513
|
)
|
|
492
514
|
|
|
493
515
|
# Add default region, which will be in resourcesDefaultRegion
|
|
@@ -496,7 +518,7 @@ class TerrascriptClient:
|
|
|
496
518
|
secret_key=config["aws_secret_access_key"],
|
|
497
519
|
region=config["resourcesDefaultRegion"],
|
|
498
520
|
skip_region_validation=True,
|
|
499
|
-
default_tags=
|
|
521
|
+
default_tags={"tags": config["tags"]},
|
|
500
522
|
)
|
|
501
523
|
|
|
502
524
|
ts += Terraform(
|
|
@@ -541,10 +563,10 @@ class TerrascriptClient:
|
|
|
541
563
|
self.accounts = {a["name"]: a for a in filtered_accounts}
|
|
542
564
|
self.uids = {a["name"]: a["uid"] for a in filtered_accounts}
|
|
543
565
|
# default_regions info is needed in populate_tf_resource_rds, even in disabled accounts
|
|
544
|
-
self.default_regions = {
|
|
566
|
+
self.default_regions: dict[str, str] = {
|
|
545
567
|
a["name"]: a["resourcesDefaultRegion"] for a in accounts
|
|
546
568
|
}
|
|
547
|
-
self.partitions = {
|
|
569
|
+
self.partitions: dict[str, str] = {
|
|
548
570
|
a["name"]: a.get("partition") or "aws" for a in filtered_accounts
|
|
549
571
|
}
|
|
550
572
|
self.rosa_auth_logtoes_zip = ""
|
|
@@ -566,19 +588,19 @@ class TerrascriptClient:
|
|
|
566
588
|
for schema in prefetch_resources_by_schemas:
|
|
567
589
|
self._resource_cache.update(self.prefetch_resources(schema))
|
|
568
590
|
|
|
569
|
-
def __enter__(self):
|
|
591
|
+
def __enter__(self) -> Self:
|
|
570
592
|
return self
|
|
571
593
|
|
|
572
|
-
def __exit__(self, *exc):
|
|
594
|
+
def __exit__(self, *exc: Any) -> None:
|
|
573
595
|
self.cleanup()
|
|
574
596
|
|
|
575
|
-
def cleanup(self):
|
|
597
|
+
def cleanup(self) -> None:
|
|
576
598
|
if self.gitlab is not None:
|
|
577
599
|
self.gitlab.cleanup()
|
|
578
600
|
|
|
579
601
|
@staticmethod
|
|
580
602
|
def state_bucket_for_account(
|
|
581
|
-
integration: str, account_name: str, config:
|
|
603
|
+
integration: str, account_name: str, config: Mapping[str, Any]
|
|
582
604
|
) -> Backend:
|
|
583
605
|
# creds
|
|
584
606
|
access_key_backend_value = config["aws_access_key_id"]
|
|
@@ -643,7 +665,7 @@ class TerrascriptClient:
|
|
|
643
665
|
f.write(r.content)
|
|
644
666
|
return zip_file
|
|
645
667
|
|
|
646
|
-
def get_logtoes_zip(self, release_url):
|
|
668
|
+
def get_logtoes_zip(self, release_url: str) -> str:
|
|
647
669
|
if not self.rosa_auth_logtoes_zip:
|
|
648
670
|
with self.rosa_auth_logtoes_zip_lock:
|
|
649
671
|
# this may have already happened, so we check again
|
|
@@ -656,7 +678,7 @@ class TerrascriptClient:
|
|
|
656
678
|
return self.rosa_auth_logtoes_zip
|
|
657
679
|
return self.download_logtoes_zip(release_url)
|
|
658
680
|
|
|
659
|
-
def download_logtoes_zip(self, release_url):
|
|
681
|
+
def download_logtoes_zip(self, release_url: str) -> str:
|
|
660
682
|
headers = {"Authorization": "token " + self.token}
|
|
661
683
|
r = requests.get(GH_BASE_URL + "/" + release_url, headers=headers, timeout=60)
|
|
662
684
|
r.raise_for_status()
|
|
@@ -670,7 +692,7 @@ class TerrascriptClient:
|
|
|
670
692
|
f.write(r.content)
|
|
671
693
|
return zip_file
|
|
672
694
|
|
|
673
|
-
def get_rosa_auth_pre_signup_zip(self, release_url):
|
|
695
|
+
def get_rosa_auth_pre_signup_zip(self, release_url: str) -> str:
|
|
674
696
|
if not self.rosa_auth_pre_signup_zip:
|
|
675
697
|
with self.rosa_auth_pre_signup_zip_lock:
|
|
676
698
|
# this may have already happened, so we check again
|
|
@@ -685,7 +707,7 @@ class TerrascriptClient:
|
|
|
685
707
|
return self.rosa_auth_pre_signup_zip
|
|
686
708
|
return self.download_rosa_auth_pre_signup_zip(release_url)
|
|
687
709
|
|
|
688
|
-
def download_rosa_auth_pre_signup_zip(self, release_url):
|
|
710
|
+
def download_rosa_auth_pre_signup_zip(self, release_url: str) -> str:
|
|
689
711
|
headers = {"Authorization": "token " + self.token}
|
|
690
712
|
r = requests.get(GH_BASE_URL + "/" + release_url, headers=headers, timeout=60)
|
|
691
713
|
r.raise_for_status()
|
|
@@ -699,7 +721,7 @@ class TerrascriptClient:
|
|
|
699
721
|
f.write(r.content)
|
|
700
722
|
return zip_file
|
|
701
723
|
|
|
702
|
-
def get_rosa_auth_pre_token_zip(self, release_url):
|
|
724
|
+
def get_rosa_auth_pre_token_zip(self, release_url: str) -> str:
|
|
703
725
|
if not self.rosa_auth_pre_token_zip:
|
|
704
726
|
with self.rosa_auth_pre_token_zip_lock:
|
|
705
727
|
# this may have already happened, so we check again
|
|
@@ -714,7 +736,7 @@ class TerrascriptClient:
|
|
|
714
736
|
return self.rosa_auth_pre_token_zip
|
|
715
737
|
return self.download_rosa_auth_pre_token_zip(release_url)
|
|
716
738
|
|
|
717
|
-
def download_rosa_auth_pre_token_zip(self, release_url):
|
|
739
|
+
def download_rosa_auth_pre_token_zip(self, release_url: str) -> str:
|
|
718
740
|
headers = {"Authorization": "token " + self.token}
|
|
719
741
|
r = requests.get(GH_BASE_URL + "/" + release_url, headers=headers, timeout=60)
|
|
720
742
|
r.raise_for_status()
|
|
@@ -744,7 +766,7 @@ class TerrascriptClient:
|
|
|
744
766
|
self.gitlab = GitLabApi(instance, secret_reader=self.secret_reader)
|
|
745
767
|
return self.gitlab
|
|
746
768
|
|
|
747
|
-
def init_jenkins(self, instance:
|
|
769
|
+
def init_jenkins(self, instance: Mapping[str, Any]) -> JenkinsApi:
|
|
748
770
|
instance_name = instance["name"]
|
|
749
771
|
if not self.jenkins_map.get(instance_name):
|
|
750
772
|
with self.jenkins_lock:
|
|
@@ -758,8 +780,8 @@ class TerrascriptClient:
|
|
|
758
780
|
return self.jenkins_map[instance_name]
|
|
759
781
|
|
|
760
782
|
def filter_disabled_accounts(
|
|
761
|
-
self, accounts: Iterable[
|
|
762
|
-
) -> list[
|
|
783
|
+
self, accounts: Iterable[MutableMapping[str, Any]]
|
|
784
|
+
) -> list[MutableMapping[str, Any]]:
|
|
763
785
|
filtered_accounts = []
|
|
764
786
|
for account in accounts:
|
|
765
787
|
integration = self.integration.replace("_", "-")
|
|
@@ -767,7 +789,7 @@ class TerrascriptClient:
|
|
|
767
789
|
filtered_accounts.append(account)
|
|
768
790
|
return filtered_accounts
|
|
769
791
|
|
|
770
|
-
def populate_configs(self, accounts: Iterable[awsh.Account]):
|
|
792
|
+
def populate_configs(self, accounts: Iterable[awsh.Account]) -> None:
|
|
771
793
|
results = threaded.run(
|
|
772
794
|
awsh.get_tf_secrets,
|
|
773
795
|
accounts,
|
|
@@ -779,16 +801,19 @@ class TerrascriptClient:
|
|
|
779
801
|
config["supportedDeploymentRegions"] = account["supportedDeploymentRegions"]
|
|
780
802
|
config["resourcesDefaultRegion"] = account["resourcesDefaultRegion"]
|
|
781
803
|
config["terraformState"] = account["terraformState"]
|
|
804
|
+
config["tags"] = dict(self.default_tags) | get_aws_account_tags(
|
|
805
|
+
account.get("organization", None)
|
|
806
|
+
)
|
|
782
807
|
self.configs[account_name] = config
|
|
783
808
|
|
|
784
|
-
def _get_partition(self, account):
|
|
809
|
+
def _get_partition(self, account: str) -> str:
|
|
785
810
|
return self.partitions.get(account) or "aws"
|
|
786
811
|
|
|
787
812
|
@staticmethod
|
|
788
|
-
def get_tf_iam_group(group_name):
|
|
813
|
+
def get_tf_iam_group(group_name: str) -> aws_iam_group:
|
|
789
814
|
return aws_iam_group(group_name, name=group_name)
|
|
790
815
|
|
|
791
|
-
def get_tf_iam_user(self, user_name):
|
|
816
|
+
def get_tf_iam_user(self, user_name: str) -> aws_iam_user:
|
|
792
817
|
return aws_iam_user(
|
|
793
818
|
user_name,
|
|
794
819
|
name=user_name,
|
|
@@ -796,8 +821,8 @@ class TerrascriptClient:
|
|
|
796
821
|
tags={"managed_by_integration": self.integration},
|
|
797
822
|
)
|
|
798
823
|
|
|
799
|
-
def populate_iam_groups(self, roles):
|
|
800
|
-
groups = {}
|
|
824
|
+
def populate_iam_groups(self, roles: Iterable[Role]) -> dict[str, dict[str, str]]:
|
|
825
|
+
groups: dict[str, dict[str, str]] = {}
|
|
801
826
|
for role in roles:
|
|
802
827
|
users = role["users"]
|
|
803
828
|
if len(users) == 0:
|
|
@@ -840,7 +865,7 @@ class TerrascriptClient:
|
|
|
840
865
|
return groups
|
|
841
866
|
|
|
842
867
|
@staticmethod
|
|
843
|
-
def _get_aws_username(user):
|
|
868
|
+
def _get_aws_username(user: Mapping[str, str]) -> str:
|
|
844
869
|
return user.get("aws_username") or user["org_username"]
|
|
845
870
|
|
|
846
871
|
@staticmethod
|
|
@@ -865,10 +890,10 @@ class TerrascriptClient:
|
|
|
865
890
|
|
|
866
891
|
def populate_iam_users(
|
|
867
892
|
self,
|
|
868
|
-
roles,
|
|
869
|
-
skip_reencrypt_accounts:
|
|
893
|
+
roles: Iterable[Role],
|
|
894
|
+
skip_reencrypt_accounts: Iterable[str],
|
|
870
895
|
appsre_pgp_key: str | None,
|
|
871
|
-
):
|
|
896
|
+
) -> bool:
|
|
872
897
|
error = False
|
|
873
898
|
for role in roles:
|
|
874
899
|
users = role["users"]
|
|
@@ -997,10 +1022,10 @@ class TerrascriptClient:
|
|
|
997
1022
|
|
|
998
1023
|
def populate_users(
|
|
999
1024
|
self,
|
|
1000
|
-
roles,
|
|
1001
|
-
skip_reencrypt_accounts:
|
|
1025
|
+
roles: Iterable[Role],
|
|
1026
|
+
skip_reencrypt_accounts: Iterable[str],
|
|
1002
1027
|
appsre_pgp_key: str | None = None,
|
|
1003
|
-
):
|
|
1028
|
+
) -> bool:
|
|
1004
1029
|
self.populate_iam_groups(roles)
|
|
1005
1030
|
err = self.populate_iam_users(
|
|
1006
1031
|
roles,
|
|
@@ -1019,7 +1044,7 @@ class TerrascriptClient:
|
|
|
1019
1044
|
|
|
1020
1045
|
@staticmethod
|
|
1021
1046
|
def get_resource_lifecycle(
|
|
1022
|
-
common_values:
|
|
1047
|
+
common_values: Mapping[str, Any],
|
|
1023
1048
|
) -> dict[str, Any] | None:
|
|
1024
1049
|
if lifecycle := common_values.get("lifecycle"):
|
|
1025
1050
|
lifecycle = NamespaceTerraformResourceLifecycleV1(**lifecycle)
|
|
@@ -1033,10 +1058,14 @@ class TerrascriptClient:
|
|
|
1033
1058
|
ignore_changes = (
|
|
1034
1059
|
"all" if "all" in lifecycle.ignore_changes else lifecycle.ignore_changes
|
|
1035
1060
|
)
|
|
1036
|
-
return lifecycle.
|
|
1061
|
+
return lifecycle.model_dump(by_alias=True) | {
|
|
1062
|
+
"ignore_changes": ignore_changes
|
|
1063
|
+
}
|
|
1037
1064
|
return None
|
|
1038
1065
|
|
|
1039
|
-
def populate_additional_providers(
|
|
1066
|
+
def populate_additional_providers(
|
|
1067
|
+
self, infra_account_name: str, accounts: Iterable[Mapping[str, Any]]
|
|
1068
|
+
) -> None:
|
|
1040
1069
|
for account in accounts:
|
|
1041
1070
|
account_name = account["name"]
|
|
1042
1071
|
assume_role = account.get("assume_role")
|
|
@@ -1046,28 +1075,18 @@ class TerrascriptClient:
|
|
|
1046
1075
|
config = self.configs[account_name]
|
|
1047
1076
|
existing_provider_aliases = {p.get("alias") for p in ts["provider"]["aws"]}
|
|
1048
1077
|
if alias not in existing_provider_aliases:
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
)
|
|
1059
|
-
else:
|
|
1060
|
-
ts += provider.aws(
|
|
1061
|
-
access_key=config["aws_access_key_id"],
|
|
1062
|
-
secret_key=config["aws_secret_access_key"],
|
|
1063
|
-
region=region,
|
|
1064
|
-
alias=alias,
|
|
1065
|
-
skip_region_validation=True,
|
|
1066
|
-
default_tags=DEFAULT_TAGS,
|
|
1067
|
-
)
|
|
1078
|
+
ts += provider.aws(
|
|
1079
|
+
access_key=config["aws_access_key_id"],
|
|
1080
|
+
secret_key=config["aws_secret_access_key"],
|
|
1081
|
+
region=region,
|
|
1082
|
+
alias=alias,
|
|
1083
|
+
skip_region_validation=True,
|
|
1084
|
+
default_tags={"tags": config["tags"]},
|
|
1085
|
+
**{"assume_role": {"role_arn": assume_role}} if assume_role else {},
|
|
1086
|
+
)
|
|
1068
1087
|
|
|
1069
1088
|
def populate_route53(
|
|
1070
|
-
self, desired_state: Iterable[
|
|
1089
|
+
self, desired_state: Iterable[Mapping[str, Any]], default_ttl: int = 300
|
|
1071
1090
|
) -> None:
|
|
1072
1091
|
for zone in desired_state:
|
|
1073
1092
|
acct_name = zone["account_name"]
|
|
@@ -1086,10 +1105,10 @@ class TerrascriptClient:
|
|
|
1086
1105
|
def populate_route53_records(
|
|
1087
1106
|
self,
|
|
1088
1107
|
acct_name: str,
|
|
1089
|
-
zone:
|
|
1108
|
+
zone: Mapping[str, Any],
|
|
1090
1109
|
zone_resource: aws_route53_zone,
|
|
1091
1110
|
default_ttl: int = 300,
|
|
1092
|
-
):
|
|
1111
|
+
) -> None:
|
|
1093
1112
|
counts = {}
|
|
1094
1113
|
for record in zone.get("records") or []:
|
|
1095
1114
|
record_fqdn = f"{record['name']}.{zone['name']}"
|
|
@@ -1166,7 +1185,7 @@ class TerrascriptClient:
|
|
|
1166
1185
|
record_resource = aws_route53_record(record_id, **record_values)
|
|
1167
1186
|
self.add_resource(acct_name, record_resource)
|
|
1168
1187
|
|
|
1169
|
-
def populate_vpc_peerings(self, desired_state):
|
|
1188
|
+
def populate_vpc_peerings(self, desired_state: Iterable[Mapping[str, Any]]) -> None:
|
|
1170
1189
|
for item in desired_state:
|
|
1171
1190
|
if item["deleted"]:
|
|
1172
1191
|
continue
|
|
@@ -1187,7 +1206,7 @@ class TerrascriptClient:
|
|
|
1187
1206
|
|
|
1188
1207
|
# Requester's side of the connection - the cluster's account
|
|
1189
1208
|
identifier = f"{requester['vpc_id']}-{accepter['vpc_id']}"
|
|
1190
|
-
values = {
|
|
1209
|
+
values: dict[str, Any] = {
|
|
1191
1210
|
# adding the alias to the provider will add this resource
|
|
1192
1211
|
# to the cluster's AWS account
|
|
1193
1212
|
"provider": "aws." + req_alias,
|
|
@@ -1308,25 +1327,32 @@ class TerrascriptClient:
|
|
|
1308
1327
|
"version": vpc_module_version,
|
|
1309
1328
|
"name": request.identifier,
|
|
1310
1329
|
"cidr": request.cidr_block.network_address,
|
|
1311
|
-
"private_subnet_tags": {"kubernetes.io/role/internal-elb": "1"},
|
|
1312
|
-
"public_subnet_tags": {"kubernetes.io/role/elb": "1"},
|
|
1313
1330
|
"create_database_subnet_group": False,
|
|
1314
1331
|
"enable_dns_hostnames": True,
|
|
1332
|
+
"vpc_tags": request.vpc_tags or {},
|
|
1315
1333
|
"tags": {
|
|
1316
1334
|
"managed_by_integration": self.integration,
|
|
1317
1335
|
},
|
|
1318
1336
|
}
|
|
1319
1337
|
|
|
1320
|
-
if request.subnets
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1338
|
+
if request.subnets:
|
|
1339
|
+
if request.subnets.public:
|
|
1340
|
+
vpc_module_values["public_subnets"] = request.subnets.public
|
|
1341
|
+
vpc_module_values["public_subnet_tags"] = (
|
|
1342
|
+
VPC_REQUEST_DEFAULT_PUBLIC_SUBNET_TAGS
|
|
1343
|
+
| (request.subnets.public_subnet_tags or {})
|
|
1344
|
+
)
|
|
1345
|
+
if request.subnets.private:
|
|
1346
|
+
vpc_module_values["private_subnets"] = request.subnets.private
|
|
1347
|
+
vpc_module_values["private_subnet_tags"] = (
|
|
1348
|
+
VPC_REQUEST_DEFAULT_PRIVATE_SUBNET_TAGS
|
|
1349
|
+
| (request.subnets.private_subnet_tags or {})
|
|
1350
|
+
)
|
|
1351
|
+
if request.subnets.availability_zones:
|
|
1352
|
+
vpc_module_values["azs"] = request.subnets.availability_zones
|
|
1353
|
+
# We only want to enable nat_gateway if we have public and private subnets
|
|
1354
|
+
if request.subnets.public and request.subnets.private:
|
|
1355
|
+
vpc_module_values["enable_nat_gateway"] = True
|
|
1330
1356
|
|
|
1331
1357
|
aws_account = request.account.name
|
|
1332
1358
|
vpc_module = Module(request.identifier, **vpc_module_values)
|
|
@@ -1367,21 +1393,24 @@ class TerrascriptClient:
|
|
|
1367
1393
|
)
|
|
1368
1394
|
self.add_resource(aws_account, vpc_cidr_block_output)
|
|
1369
1395
|
|
|
1370
|
-
if request.subnets
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1396
|
+
if request.subnets:
|
|
1397
|
+
if request.subnets.private:
|
|
1398
|
+
private_subnets_output = Output(
|
|
1399
|
+
f"{request.identifier}-private_subnets",
|
|
1400
|
+
value=f"${{module.{request.identifier}.private_subnets}}",
|
|
1401
|
+
)
|
|
1402
|
+
self.add_resource(aws_account, private_subnets_output)
|
|
1376
1403
|
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1404
|
+
if request.subnets.public:
|
|
1405
|
+
public_subnets_output = Output(
|
|
1406
|
+
f"{request.identifier}-public_subnets",
|
|
1407
|
+
value=f"${{module.{request.identifier}.public_subnets}}",
|
|
1408
|
+
)
|
|
1409
|
+
self.add_resource(aws_account, public_subnets_output)
|
|
1383
1410
|
|
|
1384
|
-
def populate_tgw_attachments(
|
|
1411
|
+
def populate_tgw_attachments(
|
|
1412
|
+
self, desired_state: Iterable[DesiredStateItem]
|
|
1413
|
+
) -> None:
|
|
1385
1414
|
for item in desired_state:
|
|
1386
1415
|
if item.deleted:
|
|
1387
1416
|
continue
|
|
@@ -1397,37 +1426,39 @@ class TerrascriptClient:
|
|
|
1397
1426
|
req_account_name = req_account.name
|
|
1398
1427
|
# Accepter's side of the connection - the cluster's account
|
|
1399
1428
|
acc_account = accepter.account
|
|
1400
|
-
acc_alias = self.get_provider_alias(acc_account.
|
|
1429
|
+
acc_alias = self.get_provider_alias(acc_account.model_dump(by_alias=True))
|
|
1401
1430
|
acc_uid = acc_account.uid
|
|
1402
1431
|
if acc_account.assume_role:
|
|
1403
1432
|
acc_uid = awsh.get_account_uid_from_arn(acc_account.assume_role)
|
|
1404
1433
|
|
|
1405
1434
|
tags = {"managed_by_integration": self.integration, "Name": connection_name}
|
|
1406
1435
|
# add resource share
|
|
1407
|
-
|
|
1436
|
+
values_share: dict[str, Any] = {
|
|
1408
1437
|
"name": connection_name,
|
|
1409
1438
|
"allow_external_principals": True,
|
|
1410
1439
|
"tags": tags,
|
|
1411
1440
|
}
|
|
1412
1441
|
if self._multiregion_account(req_account_name):
|
|
1413
|
-
|
|
1414
|
-
tf_resource_share = aws_ram_resource_share(connection_name, **
|
|
1442
|
+
values_share["provider"] = "aws." + requester.region
|
|
1443
|
+
tf_resource_share = aws_ram_resource_share(connection_name, **values_share)
|
|
1415
1444
|
self.add_resource(infra_account_name, tf_resource_share)
|
|
1416
1445
|
|
|
1417
1446
|
# share with accepter aws account
|
|
1418
|
-
|
|
1447
|
+
values_resource_principal_association: dict[str, str] = {
|
|
1419
1448
|
"principal": acc_uid,
|
|
1420
1449
|
"resource_share_arn": "${" + tf_resource_share.arn + "}",
|
|
1421
1450
|
}
|
|
1422
1451
|
if self._multiregion_account(req_account_name):
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1452
|
+
values_resource_principal_association["provider"] = (
|
|
1453
|
+
"aws." + requester.region
|
|
1454
|
+
)
|
|
1455
|
+
tf_resource_principal_association = aws_ram_principal_association(
|
|
1456
|
+
connection_name, **values_resource_principal_association
|
|
1426
1457
|
)
|
|
1427
|
-
self.add_resource(infra_account_name,
|
|
1458
|
+
self.add_resource(infra_account_name, tf_resource_principal_association)
|
|
1428
1459
|
|
|
1429
1460
|
# accept resource share from accepter aws account
|
|
1430
|
-
|
|
1461
|
+
values_share_resource_accepter: dict[str, Any] = {
|
|
1431
1462
|
"provider": "aws." + acc_alias,
|
|
1432
1463
|
"share_arn": "${" + tf_resource_share.arn + "}",
|
|
1433
1464
|
"depends_on": [
|
|
@@ -1436,7 +1467,7 @@ class TerrascriptClient:
|
|
|
1436
1467
|
],
|
|
1437
1468
|
}
|
|
1438
1469
|
tf_resource_share_accepter = aws_ram_resource_share_accepter(
|
|
1439
|
-
connection_name, **
|
|
1470
|
+
connection_name, **values_share_resource_accepter
|
|
1440
1471
|
)
|
|
1441
1472
|
self.add_resource(infra_account_name, tf_resource_share_accepter)
|
|
1442
1473
|
|
|
@@ -1446,20 +1477,23 @@ class TerrascriptClient:
|
|
|
1446
1477
|
|
|
1447
1478
|
# tgw share association
|
|
1448
1479
|
identifier = f"{requester.tgw_id}-{accepter.vpc_id}"
|
|
1449
|
-
|
|
1480
|
+
values_resource_association: dict[str, str] = {
|
|
1450
1481
|
"resource_arn": requester.tgw_arn,
|
|
1451
1482
|
"resource_share_arn": "${" + tf_resource_share.arn + "}",
|
|
1452
1483
|
}
|
|
1453
1484
|
if self._multiregion_account(req_account_name):
|
|
1454
|
-
|
|
1455
|
-
tf_resource_association = aws_ram_resource_association(
|
|
1485
|
+
values_resource_association["provider"] = "aws." + requester.region
|
|
1486
|
+
tf_resource_association = aws_ram_resource_association(
|
|
1487
|
+
identifier, **values_resource_association
|
|
1488
|
+
)
|
|
1456
1489
|
self.add_resource(infra_account_name, tf_resource_association)
|
|
1457
1490
|
|
|
1458
1491
|
# now that the tgw is shared to the cluster's aws account
|
|
1459
1492
|
# we can create a vpc attachment to the tgw
|
|
1460
1493
|
subnets_id_az = accepter.subnets_id_az
|
|
1494
|
+
assert subnets_id_az is not None # make mypy happy
|
|
1461
1495
|
subnets = self.get_az_unique_subnet_ids(subnets_id_az)
|
|
1462
|
-
|
|
1496
|
+
values_resource_attachment: dict[str, Any] = {
|
|
1463
1497
|
"provider": "aws." + acc_alias,
|
|
1464
1498
|
"subnet_ids": subnets,
|
|
1465
1499
|
"transit_gateway_id": requester.tgw_id,
|
|
@@ -1471,20 +1505,22 @@ class TerrascriptClient:
|
|
|
1471
1505
|
"tags": tags,
|
|
1472
1506
|
}
|
|
1473
1507
|
tf_resource_attachment = aws_ec2_transit_gateway_vpc_attachment(
|
|
1474
|
-
identifier, **
|
|
1508
|
+
identifier, **values_resource_attachment
|
|
1475
1509
|
)
|
|
1476
1510
|
# we send the attachment from the cluster's aws account
|
|
1477
1511
|
self.add_resource(infra_account_name, tf_resource_attachment)
|
|
1478
1512
|
|
|
1479
1513
|
# and accept the attachment in the non cluster's aws account
|
|
1480
|
-
|
|
1514
|
+
values_attachment_accepter = {
|
|
1481
1515
|
"transit_gateway_attachment_id": "${" + tf_resource_attachment.id + "}",
|
|
1482
1516
|
"tags": tags,
|
|
1483
1517
|
}
|
|
1484
1518
|
if self._multiregion_account(req_account_name):
|
|
1485
|
-
|
|
1519
|
+
values_attachment_accepter["provider"] = "aws." + requester.region
|
|
1486
1520
|
tf_resource_attachment_accepter = (
|
|
1487
|
-
aws_ec2_transit_gateway_vpc_attachment_accepter(
|
|
1521
|
+
aws_ec2_transit_gateway_vpc_attachment_accepter(
|
|
1522
|
+
identifier, **values_attachment_accepter
|
|
1523
|
+
)
|
|
1488
1524
|
)
|
|
1489
1525
|
self.add_resource(infra_account_name, tf_resource_attachment_accepter)
|
|
1490
1526
|
|
|
@@ -1530,16 +1566,16 @@ class TerrascriptClient:
|
|
|
1530
1566
|
+ f"unsupported region: {route_region}"
|
|
1531
1567
|
)
|
|
1532
1568
|
continue
|
|
1533
|
-
|
|
1569
|
+
values_gateway_router = {
|
|
1534
1570
|
"destination_cidr_block": route["cidr_block"],
|
|
1535
1571
|
"transit_gateway_attachment_id": route["tgw_attachment_id"],
|
|
1536
1572
|
"transit_gateway_route_table_id": route["tgw_route_table_id"],
|
|
1537
1573
|
}
|
|
1538
1574
|
if self._multiregion_account(req_account_name):
|
|
1539
|
-
|
|
1575
|
+
values_gateway_router["provider"] = "aws." + route_region
|
|
1540
1576
|
route_identifier = f"{identifier}-{route['tgw_id']}"
|
|
1541
1577
|
tf_resource = aws_ec2_transit_gateway_route(
|
|
1542
|
-
route_identifier, **
|
|
1578
|
+
route_identifier, **values_gateway_router
|
|
1543
1579
|
)
|
|
1544
1580
|
self.add_resource(infra_account_name, tf_resource)
|
|
1545
1581
|
|
|
@@ -1569,7 +1605,7 @@ class TerrascriptClient:
|
|
|
1569
1605
|
+ f"unsupported region: {rule_region}"
|
|
1570
1606
|
)
|
|
1571
1607
|
continue
|
|
1572
|
-
|
|
1608
|
+
values_rule = {
|
|
1573
1609
|
"type": "ingress",
|
|
1574
1610
|
"from_port": 0,
|
|
1575
1611
|
"to_port": 0,
|
|
@@ -1578,31 +1614,37 @@ class TerrascriptClient:
|
|
|
1578
1614
|
"security_group_id": rule["security_group_id"],
|
|
1579
1615
|
}
|
|
1580
1616
|
if self._multiregion_account(req_account_name):
|
|
1581
|
-
|
|
1617
|
+
values_rule["provider"] = "aws." + rule_region
|
|
1582
1618
|
rule_identifier = f"{identifier}-{rule['vpc_id']}"
|
|
1583
|
-
tf_resource = aws_security_group_rule(
|
|
1619
|
+
tf_resource = aws_security_group_rule(
|
|
1620
|
+
rule_identifier, **values_rule
|
|
1621
|
+
)
|
|
1584
1622
|
self.add_resource(infra_account_name, tf_resource)
|
|
1585
1623
|
|
|
1586
1624
|
for zone in requester.hostedzones or []:
|
|
1587
1625
|
id = f"{identifier}-{zone}"
|
|
1588
|
-
|
|
1626
|
+
values_authorization = {
|
|
1589
1627
|
"vpc_id": accepter.vpc_id,
|
|
1590
1628
|
"vpc_region": accepter.region,
|
|
1591
1629
|
"zone_id": zone,
|
|
1592
1630
|
}
|
|
1593
|
-
authorization = aws_route53_vpc_association_authorization(
|
|
1631
|
+
authorization = aws_route53_vpc_association_authorization(
|
|
1632
|
+
id, **values_authorization
|
|
1633
|
+
)
|
|
1594
1634
|
self.add_resource(infra_account_name, authorization)
|
|
1595
|
-
|
|
1635
|
+
values_association = {
|
|
1596
1636
|
"provider": "aws." + acc_alias,
|
|
1597
1637
|
"vpc_id": f"${{aws_route53_vpc_association_authorization.{id}.vpc_id}}",
|
|
1598
1638
|
"vpc_region": accepter.region,
|
|
1599
1639
|
"zone_id": f"${{aws_route53_vpc_association_authorization.{id}.zone_id}}",
|
|
1600
1640
|
}
|
|
1601
|
-
association = aws_route53_zone_association(id, **
|
|
1641
|
+
association = aws_route53_zone_association(id, **values_association)
|
|
1602
1642
|
self.add_resource(infra_account_name, association)
|
|
1603
1643
|
|
|
1604
1644
|
@staticmethod
|
|
1605
|
-
def get_az_unique_subnet_ids(
|
|
1645
|
+
def get_az_unique_subnet_ids(
|
|
1646
|
+
subnets_id_az: Iterable[Mapping[str, str]],
|
|
1647
|
+
) -> list[str]:
|
|
1606
1648
|
"""returns a list of subnet ids which are unique per az"""
|
|
1607
1649
|
results = []
|
|
1608
1650
|
azs = []
|
|
@@ -1710,7 +1752,9 @@ class TerrascriptClient:
|
|
|
1710
1752
|
|
|
1711
1753
|
self.resource_spec_inventory[spec.id_object()] = spec
|
|
1712
1754
|
|
|
1713
|
-
def populate_tf_resources(
|
|
1755
|
+
def populate_tf_resources(
|
|
1756
|
+
self, spec: ExternalResourceSpec, ocm_map: OCMMap | None = None
|
|
1757
|
+
) -> None:
|
|
1714
1758
|
if spec.provision_provider != PROVIDER_AWS:
|
|
1715
1759
|
raise UnknownProviderError(spec.provision_provider)
|
|
1716
1760
|
|
|
@@ -1769,13 +1813,13 @@ class TerrascriptClient:
|
|
|
1769
1813
|
else:
|
|
1770
1814
|
raise UnknownProviderError(provider)
|
|
1771
1815
|
|
|
1772
|
-
def populate_tf_resource_rds(self, spec):
|
|
1816
|
+
def populate_tf_resource_rds(self, spec: ExternalResourceSpec) -> None:
|
|
1773
1817
|
account = spec.provisioner_name
|
|
1774
1818
|
identifier = spec.identifier
|
|
1775
1819
|
values = self.init_values(spec)
|
|
1776
1820
|
output_prefix = spec.output_prefix
|
|
1777
1821
|
|
|
1778
|
-
tf_resources = []
|
|
1822
|
+
tf_resources: list[TFResource] = []
|
|
1779
1823
|
self.init_common_outputs(tf_resources, spec)
|
|
1780
1824
|
|
|
1781
1825
|
# we want to allow an empty name, so we
|
|
@@ -1804,7 +1848,9 @@ class TerrascriptClient:
|
|
|
1804
1848
|
# To get the provider we should use, we get the region
|
|
1805
1849
|
# and use that as an alias in the provider definition
|
|
1806
1850
|
if az:
|
|
1807
|
-
|
|
1851
|
+
region_az = self._region_from_availability_zone(az)
|
|
1852
|
+
assert region_az # make mypy happy
|
|
1853
|
+
provider = "aws." + region_az
|
|
1808
1854
|
values["provider"] = provider
|
|
1809
1855
|
if region:
|
|
1810
1856
|
provider_region = f"aws.{region}"
|
|
@@ -1844,7 +1890,7 @@ class TerrascriptClient:
|
|
|
1844
1890
|
# 'deps' should contain a list of terraform resource names
|
|
1845
1891
|
# (not full objects) that must be created
|
|
1846
1892
|
# before the actual RDS instance should be created
|
|
1847
|
-
deps = []
|
|
1893
|
+
deps: list[str] = []
|
|
1848
1894
|
|
|
1849
1895
|
parameter_group = values.pop("parameter_group", None)
|
|
1850
1896
|
if parameter_group:
|
|
@@ -1897,7 +1943,7 @@ class TerrascriptClient:
|
|
|
1897
1943
|
em_identifier = f"{identifier}-enhanced-monitoring"
|
|
1898
1944
|
em_values = {
|
|
1899
1945
|
"name": em_identifier,
|
|
1900
|
-
"assume_role_policy":
|
|
1946
|
+
"assume_role_policy": json_dumps(assume_role_policy),
|
|
1901
1947
|
}
|
|
1902
1948
|
role_tf_resource = aws_iam_role(em_identifier, **em_values)
|
|
1903
1949
|
tf_resources.append(role_tf_resource)
|
|
@@ -1905,14 +1951,14 @@ class TerrascriptClient:
|
|
|
1905
1951
|
role_res_name = self.get_dependencies([role_tf_resource])[0]
|
|
1906
1952
|
deps.append(role_res_name)
|
|
1907
1953
|
|
|
1908
|
-
|
|
1954
|
+
em_values_attachment: dict[str, Any] = {
|
|
1909
1955
|
"role": role_tf_resource.name,
|
|
1910
1956
|
"policy_arn": f"arn:{self._get_partition(account)}:iam::aws:policy/service-role/"
|
|
1911
1957
|
+ "AmazonRDSEnhancedMonitoringRole",
|
|
1912
1958
|
"depends_on": self.get_dependencies([role_tf_resource]),
|
|
1913
1959
|
}
|
|
1914
1960
|
attachment_tf_resource = aws_iam_role_policy_attachment(
|
|
1915
|
-
em_identifier, **
|
|
1961
|
+
em_identifier, **em_values_attachment
|
|
1916
1962
|
)
|
|
1917
1963
|
tf_resources.append(attachment_tf_resource)
|
|
1918
1964
|
|
|
@@ -1930,9 +1976,8 @@ class TerrascriptClient:
|
|
|
1930
1976
|
if reset_password:
|
|
1931
1977
|
password = self.generate_random_password()
|
|
1932
1978
|
else:
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
password = self.generate_random_password()
|
|
1979
|
+
db_password = spec.get_secret_field("db.password")
|
|
1980
|
+
password = db_password or self.generate_random_password()
|
|
1936
1981
|
else:
|
|
1937
1982
|
password = ""
|
|
1938
1983
|
values["password"] = password
|
|
@@ -2024,7 +2069,7 @@ class TerrascriptClient:
|
|
|
2024
2069
|
# to a provider version with this bug fix.
|
|
2025
2070
|
# https://github.com/hashicorp/terraform-provider-aws/pull/20926
|
|
2026
2071
|
if enhanced_monitoring and replica_source:
|
|
2027
|
-
sleep_vals = {}
|
|
2072
|
+
sleep_vals: dict[str, Any] = {}
|
|
2028
2073
|
sleep_vals["depends_on"] = [attachment_res_name]
|
|
2029
2074
|
sleep_vals["create_duration"] = "30s"
|
|
2030
2075
|
|
|
@@ -2117,7 +2162,7 @@ class TerrascriptClient:
|
|
|
2117
2162
|
|
|
2118
2163
|
self.add_resources(account, tf_resources)
|
|
2119
2164
|
|
|
2120
|
-
def _multiregion_account(self, name):
|
|
2165
|
+
def _multiregion_account(self, name: str) -> bool:
|
|
2121
2166
|
if name not in self.configs:
|
|
2122
2167
|
return False
|
|
2123
2168
|
|
|
@@ -2134,11 +2179,11 @@ class TerrascriptClient:
|
|
|
2134
2179
|
return spec
|
|
2135
2180
|
return None
|
|
2136
2181
|
|
|
2137
|
-
def _get_db_name_from_values(self, values:
|
|
2182
|
+
def _get_db_name_from_values(self, values: Mapping[str, Any]) -> str:
|
|
2138
2183
|
return values.get("name") or values.get("db_name") or ""
|
|
2139
2184
|
|
|
2140
2185
|
@staticmethod
|
|
2141
|
-
def _region_from_availability_zone(az):
|
|
2186
|
+
def _region_from_availability_zone(az: str) -> str | None:
|
|
2142
2187
|
# Find the region by removing the last character from the
|
|
2143
2188
|
# availability zone. Availability zone is defined like
|
|
2144
2189
|
# us-east-1a, us-east-1b, etc. If there is no availability
|
|
@@ -2148,39 +2193,75 @@ class TerrascriptClient:
|
|
|
2148
2193
|
return None
|
|
2149
2194
|
|
|
2150
2195
|
@staticmethod
|
|
2151
|
-
def _db_needs_auth(config):
|
|
2152
|
-
return
|
|
2153
|
-
"replicate_source_db" not in config
|
|
2154
|
-
and config.get("replica_source", None) is None
|
|
2196
|
+
def _db_needs_auth(config: Mapping[str, Any]) -> bool:
|
|
2197
|
+
return (
|
|
2198
|
+
"replicate_source_db" not in config and config.get("replica_source") is None
|
|
2155
2199
|
)
|
|
2156
2200
|
|
|
2157
2201
|
@staticmethod
|
|
2158
|
-
def validate_db_name(name):
|
|
2202
|
+
def validate_db_name(name: str) -> bool:
|
|
2159
2203
|
"""Handle for Error creating DB Instance:
|
|
2160
2204
|
InvalidParameterValue: DBName must begin with a letter
|
|
2161
2205
|
and contain only alphanumeric characters."""
|
|
2162
2206
|
pattern = r"^[a-zA-Z][a-zA-Z0-9_]+$"
|
|
2163
|
-
return re.search(pattern, name)
|
|
2207
|
+
return len(name) < 64 and re.search(pattern, name) is not None
|
|
2164
2208
|
|
|
2165
2209
|
@staticmethod
|
|
2166
|
-
def generate_random_password(string_length=20):
|
|
2210
|
+
def generate_random_password(string_length: int = 20) -> str:
|
|
2167
2211
|
"""Generate a random string of letters and digits"""
|
|
2168
2212
|
letters_and_digits = string.ascii_letters + string.digits
|
|
2169
2213
|
return "".join(random.choice(letters_and_digits) for i in range(string_length))
|
|
2170
2214
|
|
|
2171
|
-
|
|
2215
|
+
@staticmethod
|
|
2216
|
+
def _build_tf_resource_s3_lifecycle_rules(
|
|
2217
|
+
versioning: bool,
|
|
2218
|
+
common_values: Mapping[str, Any],
|
|
2219
|
+
) -> list[dict]:
|
|
2220
|
+
lifecycle_rules = common_values.get("lifecycle_rules") or []
|
|
2221
|
+
if versioning and not any(
|
|
2222
|
+
"noncurrent_version_expiration" in lr for lr in lifecycle_rules
|
|
2223
|
+
):
|
|
2224
|
+
# Add a default noncurrent object expiration rule
|
|
2225
|
+
# if one isn't already set
|
|
2226
|
+
rule = {
|
|
2227
|
+
"id": "expire_noncurrent_versions",
|
|
2228
|
+
"enabled": True,
|
|
2229
|
+
"noncurrent_version_expiration": {"days": 30},
|
|
2230
|
+
"expiration": {"expired_object_delete_marker": True},
|
|
2231
|
+
"abort_incomplete_multipart_upload_days": 3,
|
|
2232
|
+
}
|
|
2233
|
+
lifecycle_rules.append(rule)
|
|
2234
|
+
|
|
2235
|
+
if storage_class := common_values.get("storage_class"):
|
|
2236
|
+
sc = storage_class.upper()
|
|
2237
|
+
days = "1"
|
|
2238
|
+
if sc.endswith("_IA"):
|
|
2239
|
+
# Infrequent Access storage class has minimum 30 days
|
|
2240
|
+
# before transition
|
|
2241
|
+
days = "30"
|
|
2242
|
+
rule = {
|
|
2243
|
+
"id": sc + "_storage_class",
|
|
2244
|
+
"enabled": True,
|
|
2245
|
+
"transition": {"days": days, "storage_class": sc},
|
|
2246
|
+
"noncurrent_version_transition": {"days": days, "storage_class": sc},
|
|
2247
|
+
}
|
|
2248
|
+
lifecycle_rules.append(rule)
|
|
2249
|
+
|
|
2250
|
+
return lifecycle_rules
|
|
2251
|
+
|
|
2252
|
+
def populate_tf_resource_s3(self, spec: ExternalResourceSpec) -> aws_s3_bucket:
|
|
2172
2253
|
account = spec.provisioner_name
|
|
2173
2254
|
identifier = spec.identifier
|
|
2174
2255
|
common_values = self.init_values(spec)
|
|
2175
2256
|
output_prefix = spec.output_prefix
|
|
2176
2257
|
|
|
2177
|
-
tf_resources = []
|
|
2258
|
+
tf_resources: list[TFResource] = []
|
|
2178
2259
|
self.init_common_outputs(tf_resources, spec)
|
|
2179
2260
|
|
|
2180
2261
|
# s3 bucket
|
|
2181
2262
|
# Terraform resource reference:
|
|
2182
2263
|
# https://www.terraform.io/docs/providers/aws/r/s3_bucket.html
|
|
2183
|
-
values = {}
|
|
2264
|
+
values: dict[str, Any] = {}
|
|
2184
2265
|
values["bucket"] = identifier
|
|
2185
2266
|
versioning = common_values.get("versioning", True)
|
|
2186
2267
|
values["versioning"] = {"enabled": versioning}
|
|
@@ -2207,47 +2288,11 @@ class TerrascriptClient:
|
|
|
2207
2288
|
request_payer = common_values.get("request_payer")
|
|
2208
2289
|
if request_payer:
|
|
2209
2290
|
values["request_payer"] = request_payer
|
|
2210
|
-
lifecycle_rules
|
|
2211
|
-
|
|
2212
|
-
|
|
2291
|
+
if lifecycle_rules := self._build_tf_resource_s3_lifecycle_rules(
|
|
2292
|
+
versioning=versioning,
|
|
2293
|
+
common_values=common_values,
|
|
2294
|
+
):
|
|
2213
2295
|
values["lifecycle_rule"] = lifecycle_rules
|
|
2214
|
-
if versioning:
|
|
2215
|
-
lrs = values.get("lifecycle_rule", [])
|
|
2216
|
-
expiration_rule = False
|
|
2217
|
-
for lr in lrs:
|
|
2218
|
-
if "noncurrent_version_expiration" in lr:
|
|
2219
|
-
expiration_rule = True
|
|
2220
|
-
break
|
|
2221
|
-
if not expiration_rule:
|
|
2222
|
-
# Add a default noncurrent object expiration rule if
|
|
2223
|
-
# if one isn't already set
|
|
2224
|
-
rule = {
|
|
2225
|
-
"id": "expire_noncurrent_versions",
|
|
2226
|
-
"enabled": "true",
|
|
2227
|
-
"noncurrent_version_expiration": {"days": 30},
|
|
2228
|
-
}
|
|
2229
|
-
if len(lrs) > 0:
|
|
2230
|
-
lrs.append(rule)
|
|
2231
|
-
else:
|
|
2232
|
-
lrs = rule
|
|
2233
|
-
sc = common_values.get("storage_class")
|
|
2234
|
-
if sc:
|
|
2235
|
-
sc = sc.upper()
|
|
2236
|
-
days = "1"
|
|
2237
|
-
if sc.endswith("_IA"):
|
|
2238
|
-
# Infrequent Access storage class has minimum 30 days
|
|
2239
|
-
# before transition
|
|
2240
|
-
days = "30"
|
|
2241
|
-
rule = {
|
|
2242
|
-
"id": sc + "_storage_class",
|
|
2243
|
-
"enabled": "true",
|
|
2244
|
-
"transition": {"days": days, "storage_class": sc},
|
|
2245
|
-
"noncurrent_version_transition": {"days": days, "storage_class": sc},
|
|
2246
|
-
}
|
|
2247
|
-
if values.get("lifecycle_rule"):
|
|
2248
|
-
values["lifecycle_rule"].append(rule)
|
|
2249
|
-
else:
|
|
2250
|
-
values["lifecycle_rule"] = rule
|
|
2251
2296
|
cors_rules = common_values.get("cors_rules")
|
|
2252
2297
|
if cors_rules:
|
|
2253
2298
|
# common_values['cors_rules'] is a list of cors_rules
|
|
@@ -2297,7 +2342,7 @@ class TerrascriptClient:
|
|
|
2297
2342
|
}
|
|
2298
2343
|
],
|
|
2299
2344
|
}
|
|
2300
|
-
rc_values["assume_role_policy"] =
|
|
2345
|
+
rc_values["assume_role_policy"] = json_dumps(role)
|
|
2301
2346
|
role_resource = aws_iam_role(id, **rc_values)
|
|
2302
2347
|
tf_resources.append(role_resource)
|
|
2303
2348
|
|
|
@@ -2307,7 +2352,7 @@ class TerrascriptClient:
|
|
|
2307
2352
|
|
|
2308
2353
|
rc_values.clear()
|
|
2309
2354
|
rc_values["name"] = config["rule_name"] + "_iam_policy"
|
|
2310
|
-
policy = {
|
|
2355
|
+
policy: dict[str, Any] = {
|
|
2311
2356
|
"Version": "2012-10-17",
|
|
2312
2357
|
"Statement": [
|
|
2313
2358
|
{
|
|
@@ -2335,7 +2380,7 @@ class TerrascriptClient:
|
|
|
2335
2380
|
},
|
|
2336
2381
|
],
|
|
2337
2382
|
}
|
|
2338
|
-
rc_values["policy"] =
|
|
2383
|
+
rc_values["policy"] = json_dumps(policy)
|
|
2339
2384
|
policy_resource = aws_iam_policy(id, **rc_values)
|
|
2340
2385
|
tf_resources.append(policy_resource)
|
|
2341
2386
|
|
|
@@ -2374,6 +2419,7 @@ class TerrascriptClient:
|
|
|
2374
2419
|
if len(deps) > 0:
|
|
2375
2420
|
values["depends_on"] = self.get_dependencies(deps)
|
|
2376
2421
|
region = common_values.get("region") or self.default_regions.get(account)
|
|
2422
|
+
assert region # make mypy happy
|
|
2377
2423
|
if self._multiregion_account(account):
|
|
2378
2424
|
values["provider"] = "aws." + region
|
|
2379
2425
|
bucket_tf_resource = aws_s3_bucket(identifier, **values)
|
|
@@ -2508,10 +2554,12 @@ class TerrascriptClient:
|
|
|
2508
2554
|
# https://www.terraform.io/docs/providers/aws/r/iam_access_key.html
|
|
2509
2555
|
|
|
2510
2556
|
# iam user for bucket
|
|
2511
|
-
values = {
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2557
|
+
values = {
|
|
2558
|
+
"name": identifier,
|
|
2559
|
+
"tags": common_values["tags"],
|
|
2560
|
+
"depends_on": self.get_dependencies([bucket_tf_resource]),
|
|
2561
|
+
}
|
|
2562
|
+
|
|
2515
2563
|
user_tf_resource = aws_iam_user(identifier, **values)
|
|
2516
2564
|
tf_resources.append(user_tf_resource)
|
|
2517
2565
|
|
|
@@ -2521,8 +2569,7 @@ class TerrascriptClient:
|
|
|
2521
2569
|
)
|
|
2522
2570
|
|
|
2523
2571
|
# iam user policy for bucket
|
|
2524
|
-
values = {}
|
|
2525
|
-
values["name"] = identifier
|
|
2572
|
+
values = {"name": identifier}
|
|
2526
2573
|
|
|
2527
2574
|
action = ["s3:*Object*"]
|
|
2528
2575
|
if common_values.get("acl", "private") == "public-read":
|
|
@@ -2548,7 +2595,7 @@ class TerrascriptClient:
|
|
|
2548
2595
|
},
|
|
2549
2596
|
],
|
|
2550
2597
|
}
|
|
2551
|
-
values["policy"] =
|
|
2598
|
+
values["policy"] = json_dumps(policy)
|
|
2552
2599
|
values["depends_on"] = self.get_dependencies([user_tf_resource])
|
|
2553
2600
|
|
|
2554
2601
|
tf_aws_iam_policy = aws_iam_policy(identifier, **values)
|
|
@@ -2566,7 +2613,7 @@ class TerrascriptClient:
|
|
|
2566
2613
|
|
|
2567
2614
|
return bucket_tf_resource
|
|
2568
2615
|
|
|
2569
|
-
def populate_tf_resource_elasticache(self, spec):
|
|
2616
|
+
def populate_tf_resource_elasticache(self, spec: ExternalResourceSpec) -> None:
|
|
2570
2617
|
account = spec.provisioner_name
|
|
2571
2618
|
identifier = spec.identifier
|
|
2572
2619
|
values = self.init_values(spec)
|
|
@@ -2574,7 +2621,7 @@ class TerrascriptClient:
|
|
|
2574
2621
|
values.setdefault("replication_group_id", values["identifier"])
|
|
2575
2622
|
values.pop("identifier", None)
|
|
2576
2623
|
|
|
2577
|
-
tf_resources = []
|
|
2624
|
+
tf_resources: list[TFResource] = []
|
|
2578
2625
|
self.init_common_outputs(tf_resources, spec)
|
|
2579
2626
|
|
|
2580
2627
|
default_region = self.default_regions.get(account)
|
|
@@ -2654,19 +2701,23 @@ class TerrascriptClient:
|
|
|
2654
2701
|
|
|
2655
2702
|
self.add_resources(account, tf_resources)
|
|
2656
2703
|
|
|
2657
|
-
def populate_tf_resource_service_account(
|
|
2704
|
+
def populate_tf_resource_service_account(
|
|
2705
|
+
self, spec: ExternalResourceSpec, ocm_map: OCMMap | None = None
|
|
2706
|
+
) -> None:
|
|
2658
2707
|
account = spec.provisioner_name
|
|
2659
2708
|
identifier = spec.identifier
|
|
2660
2709
|
common_values = self.init_values(spec)
|
|
2661
2710
|
output_prefix = spec.output_prefix
|
|
2662
2711
|
|
|
2663
|
-
tf_resources = []
|
|
2712
|
+
tf_resources: list[TFResource] = []
|
|
2664
2713
|
self.init_common_outputs(tf_resources, spec)
|
|
2665
2714
|
|
|
2666
2715
|
# iam user for bucket
|
|
2667
|
-
values = {
|
|
2668
|
-
|
|
2669
|
-
|
|
2716
|
+
values = {
|
|
2717
|
+
"name": identifier,
|
|
2718
|
+
"tags": common_values["tags"],
|
|
2719
|
+
}
|
|
2720
|
+
|
|
2670
2721
|
user_tf_resource = aws_iam_user(identifier, **values)
|
|
2671
2722
|
tf_resources.append(user_tf_resource)
|
|
2672
2723
|
|
|
@@ -2750,13 +2801,15 @@ class TerrascriptClient:
|
|
|
2750
2801
|
|
|
2751
2802
|
self.add_resources(account, tf_resources)
|
|
2752
2803
|
|
|
2753
|
-
def populate_tf_resource_secrets_manager_sa(
|
|
2804
|
+
def populate_tf_resource_secrets_manager_sa(
|
|
2805
|
+
self, spec: ExternalResourceSpec
|
|
2806
|
+
) -> None:
|
|
2754
2807
|
account = spec.provisioner_name
|
|
2755
2808
|
identifier = spec.identifier
|
|
2756
2809
|
common_values = self.init_values(spec)
|
|
2757
2810
|
output_prefix = spec.output_prefix
|
|
2758
2811
|
|
|
2759
|
-
tf_resources = []
|
|
2812
|
+
tf_resources: list[TFResource] = []
|
|
2760
2813
|
self.init_common_outputs(tf_resources, spec)
|
|
2761
2814
|
|
|
2762
2815
|
secrets_prefix = common_values["secrets_prefix"]
|
|
@@ -2780,7 +2833,7 @@ class TerrascriptClient:
|
|
|
2780
2833
|
|
|
2781
2834
|
tf_resources.extend(
|
|
2782
2835
|
self.get_tf_iam_service_user(
|
|
2783
|
-
|
|
2836
|
+
None, identifier, policy, common_values["tags"], output_prefix
|
|
2784
2837
|
)
|
|
2785
2838
|
)
|
|
2786
2839
|
|
|
@@ -2790,20 +2843,20 @@ class TerrascriptClient:
|
|
|
2790
2843
|
|
|
2791
2844
|
self.add_resources(account, tf_resources)
|
|
2792
2845
|
|
|
2793
|
-
def populate_tf_resource_role(self, spec):
|
|
2846
|
+
def populate_tf_resource_role(self, spec: ExternalResourceSpec) -> None:
|
|
2794
2847
|
account = spec.provisioner_name
|
|
2795
2848
|
identifier = spec.identifier
|
|
2796
2849
|
common_values = self.init_values(spec)
|
|
2797
2850
|
output_prefix = spec.output_prefix
|
|
2798
2851
|
|
|
2799
|
-
tf_resources = []
|
|
2852
|
+
tf_resources: list[TFResource] = []
|
|
2800
2853
|
self.init_common_outputs(tf_resources, spec)
|
|
2801
2854
|
|
|
2802
2855
|
assume_role = common_values["assume_role"]
|
|
2803
2856
|
assume_role = {k: v for k, v in assume_role.items() if v is not None}
|
|
2804
2857
|
assume_action = common_values.get("assume_action") or "AssumeRole"
|
|
2805
2858
|
# assume role policy
|
|
2806
|
-
assume_role_policy = {
|
|
2859
|
+
assume_role_policy: dict[str, Any] = {
|
|
2807
2860
|
"Version": "2012-10-17",
|
|
2808
2861
|
"Statement": [
|
|
2809
2862
|
{
|
|
@@ -2818,10 +2871,10 @@ class TerrascriptClient:
|
|
|
2818
2871
|
assume_role_policy["Statement"][0]["Condition"] = assume_condition
|
|
2819
2872
|
|
|
2820
2873
|
# iam role
|
|
2821
|
-
values = {
|
|
2874
|
+
values: dict[str, Any] = {
|
|
2822
2875
|
"name": identifier,
|
|
2823
2876
|
"tags": common_values["tags"],
|
|
2824
|
-
"assume_role_policy":
|
|
2877
|
+
"assume_role_policy": json_dumps(assume_role_policy),
|
|
2825
2878
|
}
|
|
2826
2879
|
|
|
2827
2880
|
inline_policy = common_values.get("inline_policy")
|
|
@@ -2871,9 +2924,11 @@ class TerrascriptClient:
|
|
|
2871
2924
|
|
|
2872
2925
|
self.add_resources(account, tf_resources)
|
|
2873
2926
|
|
|
2874
|
-
def populate_iam_policy(
|
|
2927
|
+
def populate_iam_policy(
|
|
2928
|
+
self, account: str, name: str, policy: Mapping[str, Any]
|
|
2929
|
+
) -> None:
|
|
2875
2930
|
tf_aws_iam_policy = aws_iam_policy(
|
|
2876
|
-
f"{account}-{name}", name=name, policy=
|
|
2931
|
+
f"{account}-{name}", name=name, policy=json_dumps(policy)
|
|
2877
2932
|
)
|
|
2878
2933
|
self.add_resource(account, tf_aws_iam_policy)
|
|
2879
2934
|
|
|
@@ -2882,8 +2937,8 @@ class TerrascriptClient:
|
|
|
2882
2937
|
account: str,
|
|
2883
2938
|
name: str,
|
|
2884
2939
|
saml_provider_name: str,
|
|
2885
|
-
aws_managed_policies:
|
|
2886
|
-
customer_managed_policies:
|
|
2940
|
+
aws_managed_policies: Iterable[str],
|
|
2941
|
+
customer_managed_policies: Iterable[str] | None = None,
|
|
2887
2942
|
max_session_duration_hours: int = 1,
|
|
2888
2943
|
) -> None:
|
|
2889
2944
|
"""Manage the an IAM role needed for SAML authentication."""
|
|
@@ -2915,23 +2970,25 @@ class TerrascriptClient:
|
|
|
2915
2970
|
role_tf_resource = aws_iam_role(
|
|
2916
2971
|
f"{account}-{name}",
|
|
2917
2972
|
name=name,
|
|
2918
|
-
assume_role_policy=
|
|
2973
|
+
assume_role_policy=json_dumps(assume_role_policy),
|
|
2919
2974
|
managed_policy_arns=managed_policy_arns,
|
|
2920
2975
|
max_session_duration=max_session_duration_hours * 3600,
|
|
2921
2976
|
)
|
|
2922
2977
|
self.add_resource(account, role_tf_resource)
|
|
2923
2978
|
|
|
2924
|
-
def populate_tf_resource_sqs(self, spec):
|
|
2979
|
+
def populate_tf_resource_sqs(self, spec: ExternalResourceSpec) -> None:
|
|
2925
2980
|
account = spec.provisioner_name
|
|
2926
2981
|
identifier = spec.identifier
|
|
2927
2982
|
common_values = self.init_values(spec)
|
|
2928
2983
|
output_prefix = spec.output_prefix
|
|
2929
2984
|
uid = self.uids.get(account)
|
|
2930
2985
|
|
|
2931
|
-
tf_resources = []
|
|
2986
|
+
tf_resources: list[TFResource] = []
|
|
2932
2987
|
self.init_common_outputs(tf_resources, spec)
|
|
2933
2988
|
region = common_values.get("region") or self.default_regions.get(account)
|
|
2989
|
+
assert region # make mypy happy
|
|
2934
2990
|
specs = common_values.get("specs")
|
|
2991
|
+
assert specs is not None # make mypy happy
|
|
2935
2992
|
all_queues_per_spec = []
|
|
2936
2993
|
kms_keys = set()
|
|
2937
2994
|
for _spec in specs:
|
|
@@ -2957,7 +3014,7 @@ class TerrascriptClient:
|
|
|
2957
3014
|
all_queues.append(queue_name)
|
|
2958
3015
|
sqs_policy = values.pop("sqs_policy", None)
|
|
2959
3016
|
if sqs_policy is not None:
|
|
2960
|
-
values["policy"] =
|
|
3017
|
+
values["policy"] = json_dumps(sqs_policy)
|
|
2961
3018
|
dl_queue = values.pop("dl_queue", None)
|
|
2962
3019
|
if dl_queue is not None:
|
|
2963
3020
|
max_receive_count = int(values.pop("max_receive_count", 10))
|
|
@@ -2971,9 +3028,7 @@ class TerrascriptClient:
|
|
|
2971
3028
|
"deadLetterTargetArn": "${" + dl_data.arn + "}",
|
|
2972
3029
|
"maxReceiveCount": max_receive_count,
|
|
2973
3030
|
}
|
|
2974
|
-
values["redrive_policy"] =
|
|
2975
|
-
redrive_policy, sort_keys=True
|
|
2976
|
-
)
|
|
3031
|
+
values["redrive_policy"] = json_dumps(redrive_policy)
|
|
2977
3032
|
kms_master_key_id = values.pop("kms_master_key_id", None)
|
|
2978
3033
|
if kms_master_key_id is not None:
|
|
2979
3034
|
if kms_master_key_id.startswith("arn:"):
|
|
@@ -3005,9 +3060,11 @@ class TerrascriptClient:
|
|
|
3005
3060
|
# https://www.terraform.io/docs/providers/aws/r/iam_access_key.html
|
|
3006
3061
|
|
|
3007
3062
|
# iam user for queue
|
|
3008
|
-
values = {
|
|
3009
|
-
|
|
3010
|
-
|
|
3063
|
+
values = {
|
|
3064
|
+
"name": identifier,
|
|
3065
|
+
"tags": common_values["tags"],
|
|
3066
|
+
}
|
|
3067
|
+
|
|
3011
3068
|
user_tf_resource = aws_iam_user(identifier, **values)
|
|
3012
3069
|
tf_resources.append(user_tf_resource)
|
|
3013
3070
|
|
|
@@ -3021,9 +3078,9 @@ class TerrascriptClient:
|
|
|
3021
3078
|
policy_identifier = f"{identifier}-{policy_index}"
|
|
3022
3079
|
if len(all_queues_per_spec) == 1:
|
|
3023
3080
|
policy_identifier = identifier
|
|
3024
|
-
values = {}
|
|
3025
|
-
|
|
3026
|
-
policy = {
|
|
3081
|
+
values = {"name": policy_identifier}
|
|
3082
|
+
|
|
3083
|
+
policy: dict[str, Any] = {
|
|
3027
3084
|
"Version": "2012-10-17",
|
|
3028
3085
|
"Statement": [
|
|
3029
3086
|
{
|
|
@@ -3044,32 +3101,34 @@ class TerrascriptClient:
|
|
|
3044
3101
|
"Resource": list(kms_keys),
|
|
3045
3102
|
}
|
|
3046
3103
|
policy["Statement"].append(kms_statement)
|
|
3047
|
-
values["policy"] =
|
|
3104
|
+
values["policy"] = json_dumps(policy)
|
|
3048
3105
|
policy_tf_resource = aws_iam_policy(policy_identifier, **values)
|
|
3049
3106
|
tf_resources.append(policy_tf_resource)
|
|
3050
3107
|
|
|
3051
3108
|
# iam user policy attachment
|
|
3052
|
-
values = {
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
|
|
3057
|
-
|
|
3058
|
-
|
|
3109
|
+
values = {
|
|
3110
|
+
"user": identifier,
|
|
3111
|
+
"policy_arn": "${" + policy_tf_resource.arn + "}",
|
|
3112
|
+
"depends_on": self.get_dependencies([
|
|
3113
|
+
user_tf_resource,
|
|
3114
|
+
policy_tf_resource,
|
|
3115
|
+
]),
|
|
3116
|
+
}
|
|
3117
|
+
|
|
3059
3118
|
tf_resource = aws_iam_user_policy_attachment(policy_identifier, **values)
|
|
3060
3119
|
tf_resources.append(tf_resource)
|
|
3061
3120
|
|
|
3062
3121
|
self.add_resources(account, tf_resources)
|
|
3063
3122
|
|
|
3064
|
-
def populate_tf_resource_sns(self, spec):
|
|
3123
|
+
def populate_tf_resource_sns(self, spec: ExternalResourceSpec) -> None:
|
|
3065
3124
|
account = spec.provisioner_name
|
|
3066
3125
|
identifier = spec.identifier
|
|
3067
3126
|
common_values = self.init_values(spec)
|
|
3068
3127
|
output_prefix = spec.output_prefix
|
|
3069
3128
|
policy = common_values.get("inline_policy")
|
|
3070
3129
|
region = common_values.get("region") or self.default_regions.get(account)
|
|
3071
|
-
|
|
3072
|
-
values = {}
|
|
3130
|
+
assert region # make mypy happy
|
|
3131
|
+
values: dict[str, Any] = {}
|
|
3073
3132
|
fifo_topic = common_values.get("fifo_topic", False)
|
|
3074
3133
|
topic_name = identifier + ".fifo" if fifo_topic else identifier
|
|
3075
3134
|
|
|
@@ -3077,16 +3136,18 @@ class TerrascriptClient:
|
|
|
3077
3136
|
values["policy"] = policy
|
|
3078
3137
|
values["fifo_topic"] = fifo_topic
|
|
3079
3138
|
|
|
3080
|
-
tf_resources = []
|
|
3139
|
+
tf_resources: list[TFResource] = []
|
|
3081
3140
|
self.init_common_outputs(tf_resources, spec)
|
|
3082
3141
|
tf_resource = aws_sns_topic(identifier, **values)
|
|
3083
3142
|
tf_resources.append(tf_resource)
|
|
3084
3143
|
|
|
3085
3144
|
if "subscriptions" in common_values:
|
|
3086
|
-
subscriptions = common_values
|
|
3145
|
+
subscriptions = common_values["subscriptions"]
|
|
3087
3146
|
for index, sub in enumerate(subscriptions):
|
|
3088
|
-
sub_values = {
|
|
3089
|
-
|
|
3147
|
+
sub_values = {
|
|
3148
|
+
"topic_arn": "${aws_sns_topic" + "." + identifier + ".arn}"
|
|
3149
|
+
}
|
|
3150
|
+
|
|
3090
3151
|
protocol = sub["protocol"]
|
|
3091
3152
|
endpoint = sub["endpoint"]
|
|
3092
3153
|
if protocol == "email" and not EMAIL_REGEX.match(endpoint):
|
|
@@ -3111,17 +3172,19 @@ class TerrascriptClient:
|
|
|
3111
3172
|
tf_resources.append(Output(output_name, value=output_value))
|
|
3112
3173
|
self.add_resources(account, tf_resources)
|
|
3113
3174
|
|
|
3114
|
-
def populate_tf_resource_dynamodb(self, spec):
|
|
3175
|
+
def populate_tf_resource_dynamodb(self, spec: ExternalResourceSpec) -> None:
|
|
3115
3176
|
account = spec.provisioner_name
|
|
3116
3177
|
identifier = spec.identifier
|
|
3117
3178
|
common_values = self.init_values(spec)
|
|
3118
3179
|
output_prefix = spec.output_prefix
|
|
3119
3180
|
uid = self.uids.get(account)
|
|
3120
3181
|
|
|
3121
|
-
tf_resources = []
|
|
3182
|
+
tf_resources: list[TFResource] = []
|
|
3122
3183
|
self.init_common_outputs(tf_resources, spec)
|
|
3123
3184
|
region = common_values.get("region") or self.default_regions.get(account)
|
|
3185
|
+
assert region # make mypy happy
|
|
3124
3186
|
specs = common_values.get("specs")
|
|
3187
|
+
assert specs is not None # make mypy happy
|
|
3125
3188
|
all_tables = []
|
|
3126
3189
|
for _spec in specs:
|
|
3127
3190
|
defaults = self.get_values(_spec["defaults"])
|
|
@@ -3135,9 +3198,11 @@ class TerrascriptClient:
|
|
|
3135
3198
|
# Terraform resource reference:
|
|
3136
3199
|
# https://www.terraform.io/docs/providers/aws/r/
|
|
3137
3200
|
# dynamodb_table.html
|
|
3138
|
-
values = {
|
|
3139
|
-
|
|
3140
|
-
|
|
3201
|
+
values = {
|
|
3202
|
+
"name": table,
|
|
3203
|
+
"tags": common_values["tags"],
|
|
3204
|
+
}
|
|
3205
|
+
|
|
3141
3206
|
values.update(defaults)
|
|
3142
3207
|
values["attribute"] = attributes
|
|
3143
3208
|
if self._multiregion_account(account):
|
|
@@ -3158,9 +3223,11 @@ class TerrascriptClient:
|
|
|
3158
3223
|
# https://www.terraform.io/docs/providers/aws/r/iam_access_key.html
|
|
3159
3224
|
|
|
3160
3225
|
# iam user for table
|
|
3161
|
-
values = {
|
|
3162
|
-
|
|
3163
|
-
|
|
3226
|
+
values = {
|
|
3227
|
+
"name": identifier,
|
|
3228
|
+
"tags": common_values["tags"],
|
|
3229
|
+
}
|
|
3230
|
+
|
|
3164
3231
|
user_tf_resource = aws_iam_user(identifier, **values)
|
|
3165
3232
|
tf_resources.append(user_tf_resource)
|
|
3166
3233
|
|
|
@@ -3184,7 +3251,7 @@ class TerrascriptClient:
|
|
|
3184
3251
|
}
|
|
3185
3252
|
],
|
|
3186
3253
|
}
|
|
3187
|
-
values["policy"] =
|
|
3254
|
+
values["policy"] = json_dumps(policy)
|
|
3188
3255
|
values["depends_on"] = self.get_dependencies([user_tf_resource])
|
|
3189
3256
|
|
|
3190
3257
|
tf_aws_iam_policy = aws_iam_policy(identifier, **values)
|
|
@@ -3200,23 +3267,24 @@ class TerrascriptClient:
|
|
|
3200
3267
|
|
|
3201
3268
|
self.add_resources(account, tf_resources)
|
|
3202
3269
|
|
|
3203
|
-
def populate_tf_resource_ecr(self, spec):
|
|
3270
|
+
def populate_tf_resource_ecr(self, spec: ExternalResourceSpec) -> None:
|
|
3204
3271
|
account = spec.provisioner_name
|
|
3205
3272
|
identifier = spec.identifier
|
|
3206
3273
|
common_values = self.init_values(spec)
|
|
3207
3274
|
output_prefix = spec.output_prefix
|
|
3208
3275
|
|
|
3209
|
-
tf_resources = []
|
|
3276
|
+
tf_resources: list[TFResource] = []
|
|
3210
3277
|
self.init_common_outputs(tf_resources, spec)
|
|
3211
3278
|
|
|
3212
3279
|
# ecr repository
|
|
3213
3280
|
# Terraform resource reference:
|
|
3214
3281
|
# https://www.terraform.io/docs/providers/aws/r/ecr_repository.html
|
|
3215
|
-
values = {}
|
|
3282
|
+
values: dict[str, Any] = {}
|
|
3216
3283
|
values["name"] = identifier
|
|
3217
3284
|
values["tags"] = common_values["tags"]
|
|
3218
3285
|
|
|
3219
3286
|
region = common_values.get("region") or self.default_regions.get(account)
|
|
3287
|
+
assert region # make mypy happy
|
|
3220
3288
|
if self._multiregion_account(account):
|
|
3221
3289
|
values["provider"] = "aws." + region
|
|
3222
3290
|
ecr_tf_resource = aws_ecr_repository(identifier, **values)
|
|
@@ -3242,11 +3310,12 @@ class TerrascriptClient:
|
|
|
3242
3310
|
# https://www.terraform.io/docs/providers/aws/r/iam_access_key.html
|
|
3243
3311
|
|
|
3244
3312
|
# iam user for repository
|
|
3245
|
-
|
|
3246
|
-
|
|
3247
|
-
|
|
3248
|
-
|
|
3249
|
-
|
|
3313
|
+
values_iam_user: dict[str, Any] = {
|
|
3314
|
+
"name": identifier,
|
|
3315
|
+
"tags": common_values["tags"],
|
|
3316
|
+
"depends_on": self.get_dependencies([ecr_tf_resource]),
|
|
3317
|
+
}
|
|
3318
|
+
user_tf_resource = aws_iam_user(identifier, **values_iam_user)
|
|
3250
3319
|
tf_resources.append(user_tf_resource)
|
|
3251
3320
|
|
|
3252
3321
|
# iam access key for user
|
|
@@ -3255,8 +3324,7 @@ class TerrascriptClient:
|
|
|
3255
3324
|
)
|
|
3256
3325
|
|
|
3257
3326
|
# iam user policy for bucket
|
|
3258
|
-
|
|
3259
|
-
values["name"] = identifier
|
|
3327
|
+
values_policy: dict[str, Any] = {"name": identifier}
|
|
3260
3328
|
policy = {
|
|
3261
3329
|
"Version": "2012-10-17",
|
|
3262
3330
|
"Statement": [
|
|
@@ -3293,10 +3361,10 @@ class TerrascriptClient:
|
|
|
3293
3361
|
},
|
|
3294
3362
|
],
|
|
3295
3363
|
}
|
|
3296
|
-
|
|
3297
|
-
|
|
3364
|
+
values_policy["policy"] = json_dumps(policy)
|
|
3365
|
+
values_policy["depends_on"] = self.get_dependencies([user_tf_resource])
|
|
3298
3366
|
|
|
3299
|
-
tf_aws_iam_policy = aws_iam_policy(identifier, **
|
|
3367
|
+
tf_aws_iam_policy = aws_iam_policy(identifier, **values_policy)
|
|
3300
3368
|
tf_resources.append(tf_aws_iam_policy)
|
|
3301
3369
|
|
|
3302
3370
|
tf_aws_iam_user_policy_attachment = aws_iam_user_policy_attachment(
|
|
@@ -3309,7 +3377,7 @@ class TerrascriptClient:
|
|
|
3309
3377
|
|
|
3310
3378
|
self.add_resources(account, tf_resources)
|
|
3311
3379
|
|
|
3312
|
-
def populate_tf_resource_s3_cloudfront(self, spec):
|
|
3380
|
+
def populate_tf_resource_s3_cloudfront(self, spec: ExternalResourceSpec) -> None:
|
|
3313
3381
|
account = spec.provisioner_name
|
|
3314
3382
|
identifier = spec.identifier
|
|
3315
3383
|
common_values = self.init_values(spec)
|
|
@@ -3317,17 +3385,15 @@ class TerrascriptClient:
|
|
|
3317
3385
|
|
|
3318
3386
|
bucket_tf_resource = self.populate_tf_resource_s3(spec)
|
|
3319
3387
|
|
|
3320
|
-
tf_resources = []
|
|
3388
|
+
tf_resources: list[TFResource] = []
|
|
3321
3389
|
|
|
3322
3390
|
# cloudfront origin access identity
|
|
3323
|
-
values = {}
|
|
3324
|
-
values["comment"] = f"{identifier}-cf-identity"
|
|
3391
|
+
values = {"comment": f"{identifier}-cf-identity"}
|
|
3325
3392
|
cf_oai_tf_resource = aws_cloudfront_origin_access_identity(identifier, **values)
|
|
3326
3393
|
tf_resources.append(cf_oai_tf_resource)
|
|
3327
3394
|
|
|
3328
3395
|
# bucket policy for cloudfront
|
|
3329
|
-
|
|
3330
|
-
values["bucket"] = identifier
|
|
3396
|
+
values_policy: dict[str, Any] = {"bucket": identifier}
|
|
3331
3397
|
policy = {
|
|
3332
3398
|
"Version": "2012-10-17",
|
|
3333
3399
|
"Statement": [
|
|
@@ -3345,26 +3411,27 @@ class TerrascriptClient:
|
|
|
3345
3411
|
}
|
|
3346
3412
|
],
|
|
3347
3413
|
}
|
|
3348
|
-
|
|
3349
|
-
|
|
3414
|
+
values_policy["policy"] = json_dumps(policy)
|
|
3415
|
+
values_policy["depends_on"] = self.get_dependencies([bucket_tf_resource])
|
|
3350
3416
|
region = common_values.get("region") or self.default_regions.get(account)
|
|
3417
|
+
assert region # make mypy happy
|
|
3351
3418
|
if self._multiregion_account(account):
|
|
3352
|
-
|
|
3353
|
-
bucket_policy_tf_resource = aws_s3_bucket_policy(identifier, **
|
|
3419
|
+
values_policy["provider"] = "aws." + region
|
|
3420
|
+
bucket_policy_tf_resource = aws_s3_bucket_policy(identifier, **values_policy)
|
|
3354
3421
|
tf_resources.append(bucket_policy_tf_resource)
|
|
3355
3422
|
|
|
3356
|
-
|
|
3423
|
+
distribution_config = common_values.get("distribution_config", {})
|
|
3357
3424
|
# aws_s3_bucket_acl
|
|
3358
|
-
if "logging_config" in
|
|
3425
|
+
if "logging_config" in distribution_config:
|
|
3359
3426
|
# we could set this at a global level with a standard name like "cloudfront"
|
|
3360
3427
|
# but we need all aws accounts upgraded to aws provider >3.60 first
|
|
3361
3428
|
tf_resources.append(
|
|
3362
3429
|
aws_cloudfront_log_delivery_canonical_user_id(identifier)
|
|
3363
3430
|
)
|
|
3364
3431
|
|
|
3365
|
-
logging_config_bucket =
|
|
3432
|
+
logging_config_bucket = distribution_config["logging_config"]
|
|
3366
3433
|
acl_values = {}
|
|
3367
|
-
access_control_policy = {
|
|
3434
|
+
access_control_policy: dict[str, Any] = {
|
|
3368
3435
|
"owner": {
|
|
3369
3436
|
"id": "${data.aws_canonical_user_id.current.id}",
|
|
3370
3437
|
},
|
|
@@ -3388,7 +3455,7 @@ class TerrascriptClient:
|
|
|
3388
3455
|
}
|
|
3389
3456
|
external_account_id = logging_config_bucket.pop("external_account_id", None)
|
|
3390
3457
|
if external_account_id:
|
|
3391
|
-
external_account_policy = {
|
|
3458
|
+
external_account_policy: dict[str, Any] = {
|
|
3392
3459
|
"grantee": {
|
|
3393
3460
|
"id": external_account_id,
|
|
3394
3461
|
"type": "CanonicalUser",
|
|
@@ -3403,13 +3470,15 @@ class TerrascriptClient:
|
|
|
3403
3470
|
tf_resources.append(aws_s3_bucket_acl_resource)
|
|
3404
3471
|
|
|
3405
3472
|
# cloud front distribution
|
|
3406
|
-
|
|
3407
|
-
|
|
3473
|
+
distribution_config["tags"] = common_values["tags"]
|
|
3474
|
+
distribution_config.setdefault("default_cache_behavior", {}).setdefault(
|
|
3408
3475
|
"target_origin_id", "default"
|
|
3409
3476
|
)
|
|
3410
3477
|
origin = {
|
|
3411
3478
|
"domain_name": "${" + bucket_tf_resource.bucket_domain_name + "}",
|
|
3412
|
-
"origin_id":
|
|
3479
|
+
"origin_id": distribution_config["default_cache_behavior"][
|
|
3480
|
+
"target_origin_id"
|
|
3481
|
+
],
|
|
3413
3482
|
"s3_origin_config": {
|
|
3414
3483
|
"origin_access_identity": "origin-access-identity/cloudfront/"
|
|
3415
3484
|
+ "${"
|
|
@@ -3417,8 +3486,10 @@ class TerrascriptClient:
|
|
|
3417
3486
|
+ "}"
|
|
3418
3487
|
},
|
|
3419
3488
|
}
|
|
3420
|
-
|
|
3421
|
-
cf_distribution_tf_resource = aws_cloudfront_distribution(
|
|
3489
|
+
distribution_config["origin"] = [origin]
|
|
3490
|
+
cf_distribution_tf_resource = aws_cloudfront_distribution(
|
|
3491
|
+
identifier, **distribution_config
|
|
3492
|
+
)
|
|
3422
3493
|
tf_resources.append(cf_distribution_tf_resource)
|
|
3423
3494
|
|
|
3424
3495
|
# outputs
|
|
@@ -3443,7 +3514,7 @@ class TerrascriptClient:
|
|
|
3443
3514
|
|
|
3444
3515
|
self.add_resources(account, tf_resources)
|
|
3445
3516
|
|
|
3446
|
-
def populate_tf_resource_s3_sqs(self, spec):
|
|
3517
|
+
def populate_tf_resource_s3_sqs(self, spec: ExternalResourceSpec) -> None:
|
|
3447
3518
|
account = spec.provisioner_name
|
|
3448
3519
|
identifier = spec.identifier
|
|
3449
3520
|
common_values = self.init_values(spec)
|
|
@@ -3453,12 +3524,13 @@ class TerrascriptClient:
|
|
|
3453
3524
|
bucket_tf_resource = self.populate_tf_resource_s3(spec)
|
|
3454
3525
|
|
|
3455
3526
|
region = common_values.get("region") or self.default_regions.get(account)
|
|
3527
|
+
assert region # make mypy happy
|
|
3456
3528
|
provider = ""
|
|
3457
3529
|
if self._multiregion_account(account):
|
|
3458
3530
|
provider = "aws." + region
|
|
3459
|
-
tf_resources = []
|
|
3531
|
+
tf_resources: list[TFResource] = []
|
|
3460
3532
|
sqs_identifier = f"{identifier}-sqs"
|
|
3461
|
-
sqs_values = {"name": sqs_identifier}
|
|
3533
|
+
sqs_values: dict[str, Any] = {"name": sqs_identifier}
|
|
3462
3534
|
|
|
3463
3535
|
sqs_values["visibility_timeout_seconds"] = int(
|
|
3464
3536
|
common_values.get("visibility_timeout_seconds", 30)
|
|
@@ -3485,21 +3557,21 @@ class TerrascriptClient:
|
|
|
3485
3557
|
}
|
|
3486
3558
|
],
|
|
3487
3559
|
}
|
|
3488
|
-
sqs_values["policy"] =
|
|
3560
|
+
sqs_values["policy"] = json_dumps(sqs_policy)
|
|
3489
3561
|
|
|
3490
3562
|
kms_encryption = common_values.get("kms_encryption", False)
|
|
3491
3563
|
if kms_encryption:
|
|
3492
3564
|
kms_identifier = f"{identifier}-kms"
|
|
3493
3565
|
kms_values = {
|
|
3494
|
-
"description": "app-interface created KMS key for" + sqs_identifier
|
|
3566
|
+
"description": "app-interface created KMS key for" + sqs_identifier,
|
|
3567
|
+
"key_usage": str(
|
|
3568
|
+
common_values.get("key_usage", "ENCRYPT_DECRYPT")
|
|
3569
|
+
).upper(),
|
|
3570
|
+
"customer_master_key_spec": str(
|
|
3571
|
+
common_values.get("customer_master_key_spec", "SYMMETRIC_DEFAULT")
|
|
3572
|
+
).upper(),
|
|
3573
|
+
"is_enabled": common_values.get("is_enabled", True),
|
|
3495
3574
|
}
|
|
3496
|
-
kms_values["key_usage"] = str(
|
|
3497
|
-
common_values.get("key_usage", "ENCRYPT_DECRYPT")
|
|
3498
|
-
).upper()
|
|
3499
|
-
kms_values["customer_master_key_spec"] = str(
|
|
3500
|
-
common_values.get("customer_master_key_spec", "SYMMETRIC_DEFAULT")
|
|
3501
|
-
).upper()
|
|
3502
|
-
kms_values["is_enabled"] = common_values.get("is_enabled", True)
|
|
3503
3575
|
|
|
3504
3576
|
kms_policy = {
|
|
3505
3577
|
"Version": "2012-10-17",
|
|
@@ -3521,7 +3593,7 @@ class TerrascriptClient:
|
|
|
3521
3593
|
},
|
|
3522
3594
|
],
|
|
3523
3595
|
}
|
|
3524
|
-
kms_values["policy"] =
|
|
3596
|
+
kms_values["policy"] = json_dumps(kms_policy)
|
|
3525
3597
|
if provider:
|
|
3526
3598
|
kms_values["provider"] = provider
|
|
3527
3599
|
|
|
@@ -3575,16 +3647,16 @@ class TerrascriptClient:
|
|
|
3575
3647
|
# https://www.terraform.io/docs/providers/aws/r/iam_access_key.html
|
|
3576
3648
|
|
|
3577
3649
|
# iam user for queue
|
|
3578
|
-
values = {}
|
|
3579
|
-
values["name"] = sqs_identifier
|
|
3650
|
+
values: dict[str, Any] = {"name": sqs_identifier}
|
|
3580
3651
|
user_tf_resource = aws_iam_user(sqs_identifier, **values)
|
|
3581
3652
|
tf_resources.append(user_tf_resource)
|
|
3582
3653
|
|
|
3583
3654
|
# iam access key for user
|
|
3584
|
-
|
|
3585
|
-
|
|
3586
|
-
|
|
3587
|
-
|
|
3655
|
+
values_key: dict[str, Any] = {
|
|
3656
|
+
"user": sqs_identifier,
|
|
3657
|
+
"depends_on": self.get_dependencies([user_tf_resource]),
|
|
3658
|
+
}
|
|
3659
|
+
access_key_tf_resource = aws_iam_access_key(sqs_identifier, **values_key)
|
|
3588
3660
|
tf_resources.append(access_key_tf_resource)
|
|
3589
3661
|
# outputs
|
|
3590
3662
|
# sqs_aws_access_key_id
|
|
@@ -3597,9 +3669,8 @@ class TerrascriptClient:
|
|
|
3597
3669
|
tf_resources.append(Output(output_name, value=output_value, sensitive=True))
|
|
3598
3670
|
|
|
3599
3671
|
# iam policy for queue
|
|
3600
|
-
|
|
3601
|
-
|
|
3602
|
-
policy = {
|
|
3672
|
+
values_policy: dict[str, Any] = {"name": sqs_identifier}
|
|
3673
|
+
policy: dict[str, Any] = {
|
|
3603
3674
|
"Version": "2012-10-17",
|
|
3604
3675
|
"Statement": [
|
|
3605
3676
|
{
|
|
@@ -3620,20 +3691,21 @@ class TerrascriptClient:
|
|
|
3620
3691
|
"Resource": [sqs_values["kms_master_key_id"]],
|
|
3621
3692
|
}
|
|
3622
3693
|
policy["Statement"].append(kms_statement)
|
|
3623
|
-
|
|
3624
|
-
policy_tf_resource = aws_iam_policy(sqs_identifier, **
|
|
3694
|
+
values_policy["policy"] = json_dumps(policy)
|
|
3695
|
+
policy_tf_resource = aws_iam_policy(sqs_identifier, **values_policy)
|
|
3625
3696
|
tf_resources.append(policy_tf_resource)
|
|
3626
3697
|
|
|
3627
3698
|
# iam user policy attachment
|
|
3628
|
-
|
|
3629
|
-
|
|
3630
|
-
|
|
3631
|
-
|
|
3632
|
-
|
|
3633
|
-
|
|
3634
|
-
|
|
3699
|
+
values_user_policy: dict[str, Any] = {
|
|
3700
|
+
"user": sqs_identifier,
|
|
3701
|
+
"policy_arn": "${" + policy_tf_resource.arn + "}",
|
|
3702
|
+
"depends_on": self.get_dependencies([
|
|
3703
|
+
user_tf_resource,
|
|
3704
|
+
policy_tf_resource,
|
|
3705
|
+
]),
|
|
3706
|
+
}
|
|
3635
3707
|
user_policy_attachment_tf_resource = aws_iam_user_policy_attachment(
|
|
3636
|
-
sqs_identifier, **
|
|
3708
|
+
sqs_identifier, **values_user_policy
|
|
3637
3709
|
)
|
|
3638
3710
|
tf_resources.append(user_policy_attachment_tf_resource)
|
|
3639
3711
|
|
|
@@ -3644,13 +3716,13 @@ class TerrascriptClient:
|
|
|
3644
3716
|
|
|
3645
3717
|
self.add_resources(account, tf_resources)
|
|
3646
3718
|
|
|
3647
|
-
def populate_tf_resource_cloudwatch(self, spec):
|
|
3719
|
+
def populate_tf_resource_cloudwatch(self, spec: ExternalResourceSpec) -> None:
|
|
3648
3720
|
account = spec.provisioner_name
|
|
3649
3721
|
identifier = spec.identifier
|
|
3650
3722
|
common_values = self.init_values(spec)
|
|
3651
3723
|
output_prefix = spec.output_prefix
|
|
3652
3724
|
|
|
3653
|
-
tf_resources = []
|
|
3725
|
+
tf_resources: list[TFResource] = []
|
|
3654
3726
|
self.init_common_outputs(tf_resources, spec)
|
|
3655
3727
|
|
|
3656
3728
|
# ecr repository
|
|
@@ -3666,6 +3738,7 @@ class TerrascriptClient:
|
|
|
3666
3738
|
}
|
|
3667
3739
|
|
|
3668
3740
|
region = common_values.get("region") or self.default_regions.get(account)
|
|
3741
|
+
assert region # make mypy happy
|
|
3669
3742
|
provider = ""
|
|
3670
3743
|
if self._multiregion_account(account):
|
|
3671
3744
|
provider = "aws." + region
|
|
@@ -3689,7 +3762,7 @@ class TerrascriptClient:
|
|
|
3689
3762
|
role_identifier = f"{identifier}-lambda-execution-role"
|
|
3690
3763
|
role_values = {
|
|
3691
3764
|
"name": role_identifier,
|
|
3692
|
-
"assume_role_policy":
|
|
3765
|
+
"assume_role_policy": json_dumps(assume_role_policy),
|
|
3693
3766
|
}
|
|
3694
3767
|
|
|
3695
3768
|
role_tf_resource = aws_iam_role(role_identifier, **role_values)
|
|
@@ -3721,7 +3794,7 @@ class TerrascriptClient:
|
|
|
3721
3794
|
|
|
3722
3795
|
policy_values = {
|
|
3723
3796
|
"role": "${" + role_tf_resource.id + "}",
|
|
3724
|
-
"policy":
|
|
3797
|
+
"policy": json_dumps(policy),
|
|
3725
3798
|
}
|
|
3726
3799
|
policy_tf_resource = aws_iam_role_policy(policy_identifier, **policy_values)
|
|
3727
3800
|
tf_resources.append(policy_tf_resource)
|
|
@@ -3741,29 +3814,26 @@ class TerrascriptClient:
|
|
|
3741
3814
|
"filename": zip_file,
|
|
3742
3815
|
"source_code_hash": '${filebase64sha256("' + zip_file + '")}',
|
|
3743
3816
|
"role": "${" + role_tf_resource.arn + "}",
|
|
3744
|
-
|
|
3745
|
-
|
|
3746
|
-
|
|
3747
|
-
|
|
3748
|
-
|
|
3749
|
-
|
|
3750
|
-
|
|
3751
|
-
|
|
3752
|
-
lambda_values["vpc_config"] = {
|
|
3753
|
-
"subnet_ids": "${data.aws_elasticsearch_domain."
|
|
3754
|
-
+ es_identifier
|
|
3755
|
-
+ ".vpc_options.0.subnet_ids}",
|
|
3756
|
-
"security_group_ids": "${data.aws_elasticsearch_domain."
|
|
3757
|
-
+ es_identifier
|
|
3758
|
-
+ ".vpc_options.0.security_group_ids}",
|
|
3759
|
-
}
|
|
3760
|
-
|
|
3761
|
-
lambda_values["environment"] = {
|
|
3762
|
-
"variables": {
|
|
3763
|
-
"es_endpoint": "${data.aws_elasticsearch_domain."
|
|
3817
|
+
"function_name": lambda_identifier,
|
|
3818
|
+
"runtime": common_values.get("runtime", "nodejs18.x"),
|
|
3819
|
+
"timeout": common_values.get("timeout", 30),
|
|
3820
|
+
"handler": common_values.get("handler", "index.handler"),
|
|
3821
|
+
"memory_size": common_values.get("memory_size", 128),
|
|
3822
|
+
"vpc_config": {
|
|
3823
|
+
"subnet_ids": "${data.aws_elasticsearch_domain."
|
|
3764
3824
|
+ es_identifier
|
|
3765
|
-
+ ".
|
|
3766
|
-
|
|
3825
|
+
+ ".vpc_options.0.subnet_ids}",
|
|
3826
|
+
"security_group_ids": "${data.aws_elasticsearch_domain."
|
|
3827
|
+
+ es_identifier
|
|
3828
|
+
+ ".vpc_options.0.security_group_ids}",
|
|
3829
|
+
},
|
|
3830
|
+
"environment": {
|
|
3831
|
+
"variables": {
|
|
3832
|
+
"es_endpoint": "${data.aws_elasticsearch_domain."
|
|
3833
|
+
+ es_identifier
|
|
3834
|
+
+ ".endpoint}"
|
|
3835
|
+
}
|
|
3836
|
+
},
|
|
3767
3837
|
}
|
|
3768
3838
|
|
|
3769
3839
|
if provider:
|
|
@@ -3852,7 +3922,7 @@ class TerrascriptClient:
|
|
|
3852
3922
|
}
|
|
3853
3923
|
values = {
|
|
3854
3924
|
"name": identifier,
|
|
3855
|
-
"policy":
|
|
3925
|
+
"policy": json_dumps(policy),
|
|
3856
3926
|
"depends_on": self.get_dependencies([user_tf_resource]),
|
|
3857
3927
|
}
|
|
3858
3928
|
|
|
@@ -3869,13 +3939,13 @@ class TerrascriptClient:
|
|
|
3869
3939
|
|
|
3870
3940
|
self.add_resources(account, tf_resources)
|
|
3871
3941
|
|
|
3872
|
-
def populate_tf_resource_kms(self, spec):
|
|
3942
|
+
def populate_tf_resource_kms(self, spec: ExternalResourceSpec) -> None:
|
|
3873
3943
|
account = spec.provisioner_name
|
|
3874
3944
|
identifier = spec.identifier
|
|
3875
3945
|
values = self.init_values(spec)
|
|
3876
3946
|
output_prefix = spec.output_prefix
|
|
3877
3947
|
|
|
3878
|
-
tf_resources = []
|
|
3948
|
+
tf_resources: list[TFResource] = []
|
|
3879
3949
|
self.init_common_outputs(tf_resources, spec)
|
|
3880
3950
|
values.pop("identifier", None)
|
|
3881
3951
|
|
|
@@ -3892,6 +3962,7 @@ class TerrascriptClient:
|
|
|
3892
3962
|
if key in values:
|
|
3893
3963
|
values[key] = values[key].upper()
|
|
3894
3964
|
region = values.pop("region", None) or self.default_regions.get(account)
|
|
3965
|
+
assert region # make mypy happy
|
|
3895
3966
|
if self._multiregion_account(account):
|
|
3896
3967
|
values["provider"] = "aws." + region
|
|
3897
3968
|
|
|
@@ -3903,9 +3974,10 @@ class TerrascriptClient:
|
|
|
3903
3974
|
output_value = "${" + tf_resource.key_id + "}"
|
|
3904
3975
|
tf_resources.append(Output(output_name, value=output_value))
|
|
3905
3976
|
|
|
3906
|
-
alias_values = {
|
|
3907
|
-
|
|
3908
|
-
|
|
3977
|
+
alias_values = {
|
|
3978
|
+
"name": "alias/" + identifier,
|
|
3979
|
+
"target_key_id": "${aws_kms_key." + identifier + ".key_id}",
|
|
3980
|
+
}
|
|
3909
3981
|
if self._multiregion_account(account):
|
|
3910
3982
|
alias_values["provider"] = "aws." + region
|
|
3911
3983
|
tf_resource = aws_kms_alias(identifier, **alias_values)
|
|
@@ -3913,28 +3985,30 @@ class TerrascriptClient:
|
|
|
3913
3985
|
|
|
3914
3986
|
self.add_resources(account, tf_resources)
|
|
3915
3987
|
|
|
3916
|
-
def populate_tf_resource_kinesis(self, spec):
|
|
3988
|
+
def populate_tf_resource_kinesis(self, spec: ExternalResourceSpec) -> None:
|
|
3917
3989
|
account = spec.provisioner_name
|
|
3918
3990
|
identifier = spec.identifier
|
|
3919
3991
|
common_values = self.init_values(spec)
|
|
3920
3992
|
output_prefix = spec.output_prefix
|
|
3921
3993
|
|
|
3922
|
-
tf_resources = []
|
|
3994
|
+
tf_resources: list[TFResource] = []
|
|
3923
3995
|
self.init_common_outputs(tf_resources, spec)
|
|
3924
3996
|
|
|
3925
|
-
tags = common_values["tags"]
|
|
3926
|
-
kinesis_values = {
|
|
3997
|
+
tags: dict[str, str] = common_values["tags"]
|
|
3998
|
+
kinesis_values: dict[str, Any] = {
|
|
3927
3999
|
"name": identifier,
|
|
3928
4000
|
"tags": tags,
|
|
4001
|
+
"shard_count": common_values.get("shard_count"),
|
|
4002
|
+
"retention_period": common_values.get("retention_period", 24),
|
|
4003
|
+
"encryption_type": common_values.get("encryption_type", None),
|
|
3929
4004
|
}
|
|
3930
|
-
|
|
3931
|
-
kinesis_values["retention_period"] = common_values.get("retention_period", 24)
|
|
3932
|
-
kinesis_values["encryption_type"] = common_values.get("encryption_type", None)
|
|
4005
|
+
|
|
3933
4006
|
if kinesis_values["encryption_type"] == "KMS":
|
|
3934
4007
|
kinesis_values["kms_key_id"] = common_values.get("kms_key_id")
|
|
3935
4008
|
|
|
3936
4009
|
# get region and set provider if required
|
|
3937
4010
|
region = common_values.get("region") or self.default_regions.get(account)
|
|
4011
|
+
assert region # make mypy happy
|
|
3938
4012
|
provider = ""
|
|
3939
4013
|
if self._multiregion_account(account):
|
|
3940
4014
|
provider = "aws." + region
|
|
@@ -3969,7 +4043,7 @@ class TerrascriptClient:
|
|
|
3969
4043
|
role_identifier = f"{identifier}-lambda-execution-role"
|
|
3970
4044
|
role_values = {
|
|
3971
4045
|
"name": role_identifier,
|
|
3972
|
-
"assume_role_policy":
|
|
4046
|
+
"assume_role_policy": json_dumps(assume_role_policy),
|
|
3973
4047
|
"tags": tags,
|
|
3974
4048
|
}
|
|
3975
4049
|
|
|
@@ -4006,7 +4080,7 @@ class TerrascriptClient:
|
|
|
4006
4080
|
policy_tf_resource = aws_iam_policy(
|
|
4007
4081
|
policy_identifier,
|
|
4008
4082
|
name=policy_identifier,
|
|
4009
|
-
policy=
|
|
4083
|
+
policy=json_dumps(policy),
|
|
4010
4084
|
tags=tags,
|
|
4011
4085
|
)
|
|
4012
4086
|
tf_resources.append(policy_tf_resource)
|
|
@@ -4054,34 +4128,31 @@ class TerrascriptClient:
|
|
|
4054
4128
|
"source_code_hash": '${filebase64sha256("' + zip_file + '")}',
|
|
4055
4129
|
"role": "${" + role_tf_resource.arn + "}",
|
|
4056
4130
|
"tags": tags,
|
|
4057
|
-
|
|
4058
|
-
|
|
4059
|
-
|
|
4060
|
-
|
|
4061
|
-
|
|
4062
|
-
|
|
4063
|
-
|
|
4064
|
-
)
|
|
4065
|
-
lambda_values["memory_size"] = common_values.get("memory_size", 128)
|
|
4066
|
-
|
|
4067
|
-
lambda_values["vpc_config"] = {
|
|
4068
|
-
"subnet_ids": "${data.aws_elasticsearch_domain."
|
|
4069
|
-
+ es_identifier
|
|
4070
|
-
+ ".vpc_options.0.subnet_ids}",
|
|
4071
|
-
"security_group_ids": "${data.aws_elasticsearch_domain."
|
|
4072
|
-
+ es_identifier
|
|
4073
|
-
+ ".vpc_options.0.security_group_ids}",
|
|
4074
|
-
}
|
|
4075
|
-
|
|
4076
|
-
index_prefix = common_values.get("index_prefix", f"{identifier}-")
|
|
4077
|
-
lambda_values["environment"] = {
|
|
4078
|
-
"variables": {
|
|
4079
|
-
"es_endpoint": "${data.aws_elasticsearch_domain."
|
|
4131
|
+
"function_name": lambda_identifier,
|
|
4132
|
+
"runtime": common_values.get("runtime", "python3.9"),
|
|
4133
|
+
"timeout": common_values.get("timeout", 30),
|
|
4134
|
+
"handler": common_values.get("handler", "lambda_function.handler"),
|
|
4135
|
+
"memory_size": common_values.get("memory_size", 128),
|
|
4136
|
+
"vpc_config": {
|
|
4137
|
+
"subnet_ids": "${data.aws_elasticsearch_domain."
|
|
4080
4138
|
+ es_identifier
|
|
4081
|
-
+ ".
|
|
4082
|
-
"
|
|
4083
|
-
|
|
4139
|
+
+ ".vpc_options.0.subnet_ids}",
|
|
4140
|
+
"security_group_ids": "${data.aws_elasticsearch_domain."
|
|
4141
|
+
+ es_identifier
|
|
4142
|
+
+ ".vpc_options.0.security_group_ids}",
|
|
4143
|
+
},
|
|
4144
|
+
"environment": {
|
|
4145
|
+
"variables": {
|
|
4146
|
+
"es_endpoint": "${data.aws_elasticsearch_domain."
|
|
4147
|
+
+ es_identifier
|
|
4148
|
+
+ ".endpoint}",
|
|
4149
|
+
"index_prefix": common_values.get(
|
|
4150
|
+
"index_prefix", f"{identifier}-"
|
|
4151
|
+
),
|
|
4152
|
+
}
|
|
4153
|
+
},
|
|
4084
4154
|
}
|
|
4155
|
+
|
|
4085
4156
|
secret_name = es_resource.get_secret_field("secret_name")
|
|
4086
4157
|
if secret_name:
|
|
4087
4158
|
lambda_values["environment"]["variables"]["secret_name"] = secret_name
|
|
@@ -4160,7 +4231,9 @@ class TerrascriptClient:
|
|
|
4160
4231
|
self.add_resources(account, tf_resources)
|
|
4161
4232
|
|
|
4162
4233
|
@staticmethod
|
|
4163
|
-
def _get_retention_in_days(
|
|
4234
|
+
def _get_retention_in_days(
|
|
4235
|
+
values: Mapping[str, Any], account: str, identifier: str
|
|
4236
|
+
) -> int:
|
|
4164
4237
|
default_retention_in_days = 14
|
|
4165
4238
|
allowed_retention_in_days = [
|
|
4166
4239
|
1,
|
|
@@ -4194,17 +4267,21 @@ class TerrascriptClient:
|
|
|
4194
4267
|
return retention_in_days
|
|
4195
4268
|
|
|
4196
4269
|
def get_tf_iam_service_user(
|
|
4197
|
-
self,
|
|
4198
|
-
|
|
4270
|
+
self,
|
|
4271
|
+
dep_tf_resource: TFResource | None,
|
|
4272
|
+
identifier: str,
|
|
4273
|
+
policy: Mapping[str, Any],
|
|
4274
|
+
tags: Mapping[str, str],
|
|
4275
|
+
output_prefix: str,
|
|
4276
|
+
) -> list[TFResource]:
|
|
4199
4277
|
# iam resources
|
|
4200
4278
|
# Terraform resource reference:
|
|
4201
4279
|
# https://www.terraform.io/docs/providers/aws/r/iam_access_key.html
|
|
4202
|
-
tf_resources = []
|
|
4280
|
+
tf_resources: list[TFResource] = []
|
|
4203
4281
|
|
|
4204
4282
|
# iam user
|
|
4205
|
-
values = {}
|
|
4206
|
-
|
|
4207
|
-
values["tags"] = tags
|
|
4283
|
+
values: dict[str, Any] = {"name": identifier, "tags": tags}
|
|
4284
|
+
|
|
4208
4285
|
if dep_tf_resource:
|
|
4209
4286
|
values["depends_on"] = self.get_dependencies([dep_tf_resource])
|
|
4210
4287
|
user_tf_resource = aws_iam_user(identifier, **values)
|
|
@@ -4216,12 +4293,13 @@ class TerrascriptClient:
|
|
|
4216
4293
|
)
|
|
4217
4294
|
|
|
4218
4295
|
# iam user policy
|
|
4219
|
-
|
|
4220
|
-
|
|
4221
|
-
|
|
4222
|
-
|
|
4296
|
+
values_policy: dict[str, Any] = {
|
|
4297
|
+
"name": identifier,
|
|
4298
|
+
"policy": json_dumps(policy),
|
|
4299
|
+
"depends_on": self.get_dependencies([user_tf_resource]),
|
|
4300
|
+
}
|
|
4223
4301
|
|
|
4224
|
-
tf_aws_iam_policy = aws_iam_policy(identifier, **
|
|
4302
|
+
tf_aws_iam_policy = aws_iam_policy(identifier, **values_policy)
|
|
4225
4303
|
tf_resources.append(tf_aws_iam_policy)
|
|
4226
4304
|
|
|
4227
4305
|
tf_aws_iam_user_policy_attachment = aws_iam_user_policy_attachment(
|
|
@@ -4234,11 +4312,15 @@ class TerrascriptClient:
|
|
|
4234
4312
|
|
|
4235
4313
|
return tf_resources
|
|
4236
4314
|
|
|
4237
|
-
def get_tf_iam_access_key(
|
|
4238
|
-
|
|
4239
|
-
|
|
4240
|
-
|
|
4241
|
-
values[
|
|
4315
|
+
def get_tf_iam_access_key(
|
|
4316
|
+
self, user_tf_resource: aws_iam_user, identifier: str, output_prefix: str
|
|
4317
|
+
) -> list[TFResource]:
|
|
4318
|
+
tf_resources: list[TFResource] = []
|
|
4319
|
+
values: dict[str, Any] = {
|
|
4320
|
+
"user": identifier,
|
|
4321
|
+
"depends_on": self.get_dependencies([user_tf_resource]),
|
|
4322
|
+
}
|
|
4323
|
+
|
|
4242
4324
|
tf_resource = aws_iam_access_key(identifier, **values)
|
|
4243
4325
|
tf_resources.append(tf_resource)
|
|
4244
4326
|
# outputs
|
|
@@ -4253,11 +4335,11 @@ class TerrascriptClient:
|
|
|
4253
4335
|
|
|
4254
4336
|
return tf_resources
|
|
4255
4337
|
|
|
4256
|
-
def add_resources(self, account, tf_resources):
|
|
4338
|
+
def add_resources(self, account: str, tf_resources: Iterable[TFResource]) -> None:
|
|
4257
4339
|
for r in tf_resources:
|
|
4258
4340
|
self.add_resource(account, r)
|
|
4259
4341
|
|
|
4260
|
-
def add_resource(self, account, tf_resource):
|
|
4342
|
+
def add_resource(self, account: str, tf_resource: TFResource) -> None:
|
|
4261
4343
|
if account not in self.locks:
|
|
4262
4344
|
logging.debug(
|
|
4263
4345
|
f"integration {self.integration} is disabled for account {account}. "
|
|
@@ -4267,7 +4349,7 @@ class TerrascriptClient:
|
|
|
4267
4349
|
with self.locks[account]:
|
|
4268
4350
|
self.tss[account].add(tf_resource)
|
|
4269
4351
|
|
|
4270
|
-
def add_moved(self, account: str, moved: Moved):
|
|
4352
|
+
def add_moved(self, account: str, moved: Moved) -> None:
|
|
4271
4353
|
if account not in self.locks:
|
|
4272
4354
|
logging.debug(
|
|
4273
4355
|
f"integration {self.integration} is disabled for account {account}. "
|
|
@@ -4331,12 +4413,11 @@ class TerrascriptClient:
|
|
|
4331
4413
|
|
|
4332
4414
|
:return: key is AWS account name and value is terraform configuration
|
|
4333
4415
|
"""
|
|
4334
|
-
return {
|
|
4335
|
-
name: json.dumps(ts, indent=2, sort_keys=True)
|
|
4336
|
-
for name, ts in self.tss.items()
|
|
4337
|
-
}
|
|
4416
|
+
return {name: json_dumps(ts, indent=2) for name, ts in self.tss.items()}
|
|
4338
4417
|
|
|
4339
|
-
def init_values(
|
|
4418
|
+
def init_values(
|
|
4419
|
+
self, spec: ExternalResourceSpec, init_tags: bool = True
|
|
4420
|
+
) -> dict[str, Any]:
|
|
4340
4421
|
"""
|
|
4341
4422
|
Initialize the values of the terraform resource and merge the defaults and
|
|
4342
4423
|
overrides.
|
|
@@ -4389,7 +4470,7 @@ class TerrascriptClient:
|
|
|
4389
4470
|
return values
|
|
4390
4471
|
|
|
4391
4472
|
@staticmethod
|
|
4392
|
-
def aggregate_values(values):
|
|
4473
|
+
def aggregate_values(values: dict[str, Any]) -> None:
|
|
4393
4474
|
split_char = "."
|
|
4394
4475
|
copy = values.copy()
|
|
4395
4476
|
for k, v in copy.items():
|
|
@@ -4403,18 +4484,17 @@ class TerrascriptClient:
|
|
|
4403
4484
|
values.pop(k, None)
|
|
4404
4485
|
|
|
4405
4486
|
@staticmethod
|
|
4406
|
-
def override_values(values, overrides):
|
|
4487
|
+
def override_values(values: dict[str, Any], overrides: str | None) -> None:
|
|
4407
4488
|
if overrides is None:
|
|
4408
4489
|
return
|
|
4409
4490
|
data = json.loads(overrides)
|
|
4410
|
-
|
|
4411
|
-
values[k] = v
|
|
4491
|
+
values.update(data)
|
|
4412
4492
|
|
|
4413
4493
|
def init_common_outputs(
|
|
4414
4494
|
self,
|
|
4415
|
-
tf_resources: list[
|
|
4495
|
+
tf_resources: list[TFResource],
|
|
4416
4496
|
spec: ExternalResourceSpec,
|
|
4417
|
-
):
|
|
4497
|
+
) -> None:
|
|
4418
4498
|
output_format = "{}__{}_{}"
|
|
4419
4499
|
# cluster
|
|
4420
4500
|
output_name = output_format.format(
|
|
@@ -4445,15 +4525,15 @@ class TerrascriptClient:
|
|
|
4445
4525
|
output_name = output_format.format(
|
|
4446
4526
|
spec.output_prefix, self.integration_prefix, "annotations"
|
|
4447
4527
|
)
|
|
4448
|
-
anno_json =
|
|
4528
|
+
anno_json = json_dumps(spec.annotations()).encode("utf-8")
|
|
4449
4529
|
output_value = base64.b64encode(anno_json).decode()
|
|
4450
4530
|
tf_resources.append(Output(output_name, value=output_value))
|
|
4451
4531
|
|
|
4452
|
-
def prefetch_resources(self, schema) -> dict[str, dict[str, str]]:
|
|
4532
|
+
def prefetch_resources(self, schema: str) -> dict[str, dict[str, str]]:
|
|
4453
4533
|
gqlapi = gql.get_api()
|
|
4454
4534
|
return {r["path"]: r for r in gqlapi.get_resources_by_schema(schema)}
|
|
4455
4535
|
|
|
4456
|
-
def get_raw_values(self, path) -> dict[str, str]:
|
|
4536
|
+
def get_raw_values(self, path: str) -> dict[str, str]:
|
|
4457
4537
|
if path in self._resource_cache:
|
|
4458
4538
|
return self._resource_cache[path]
|
|
4459
4539
|
|
|
@@ -4482,7 +4562,7 @@ class TerrascriptClient:
|
|
|
4482
4562
|
]
|
|
4483
4563
|
|
|
4484
4564
|
@staticmethod
|
|
4485
|
-
def get_elasticsearch_service_role_tf_resource():
|
|
4565
|
+
def get_elasticsearch_service_role_tf_resource() -> aws_iam_service_linked_role:
|
|
4486
4566
|
"""Service role for ElasticSearch."""
|
|
4487
4567
|
service_role = {
|
|
4488
4568
|
"aws_service_name": "es.amazonaws.com",
|
|
@@ -4490,7 +4570,7 @@ class TerrascriptClient:
|
|
|
4490
4570
|
return aws_iam_service_linked_role("elasticsearch", **service_role)
|
|
4491
4571
|
|
|
4492
4572
|
@staticmethod
|
|
4493
|
-
def is_elasticsearch_domain_name_valid(name):
|
|
4573
|
+
def is_elasticsearch_domain_name_valid(name: str) -> bool:
|
|
4494
4574
|
"""Handle for Error creating Elasticsearch:
|
|
4495
4575
|
InvalidParameterValue: Elasticsearch domain name must start with a
|
|
4496
4576
|
lowercase letter and must be between 3 and 28 characters. Valid
|
|
@@ -4498,7 +4578,7 @@ class TerrascriptClient:
|
|
|
4498
4578
|
if len(name) < 3 or len(name) > 28:
|
|
4499
4579
|
return False
|
|
4500
4580
|
pattern = r"^[a-z][a-z0-9-]+$"
|
|
4501
|
-
return re.search(pattern, name)
|
|
4581
|
+
return re.search(pattern, name) is not None
|
|
4502
4582
|
|
|
4503
4583
|
@staticmethod
|
|
4504
4584
|
def elasticsearch_log_group_identifier(
|
|
@@ -4585,7 +4665,7 @@ class TerrascriptClient:
|
|
|
4585
4665
|
}
|
|
4586
4666
|
log_groups_policy_values = {
|
|
4587
4667
|
"policy_name": "es-log-publishing-permissions",
|
|
4588
|
-
"policy_document":
|
|
4668
|
+
"policy_document": json_dumps(log_groups_policy),
|
|
4589
4669
|
}
|
|
4590
4670
|
resource_policy = aws_cloudwatch_log_resource_policy(
|
|
4591
4671
|
"es_log_publishing_resource_policy",
|
|
@@ -4600,7 +4680,7 @@ class TerrascriptClient:
|
|
|
4600
4680
|
resource: Mapping[str, Any],
|
|
4601
4681
|
values: Mapping[str, Any],
|
|
4602
4682
|
output_prefix: str,
|
|
4603
|
-
) -> tuple[list[
|
|
4683
|
+
) -> tuple[list[TFResource], list[dict[str, object]]]:
|
|
4604
4684
|
"""
|
|
4605
4685
|
Generate cloud_watch_log_group terraform_resources
|
|
4606
4686
|
for the given resource. Further, generate
|
|
@@ -4608,7 +4688,7 @@ class TerrascriptClient:
|
|
|
4608
4688
|
by the consumer.
|
|
4609
4689
|
"""
|
|
4610
4690
|
es_log_group_retention_days = 90
|
|
4611
|
-
tf_resources = []
|
|
4691
|
+
tf_resources: list[TFResource] = []
|
|
4612
4692
|
publishing_options = []
|
|
4613
4693
|
|
|
4614
4694
|
# res.get('', []) won't work, as publish_log_types is
|
|
@@ -4711,13 +4791,13 @@ class TerrascriptClient:
|
|
|
4711
4791
|
|
|
4712
4792
|
return advanced_security_options
|
|
4713
4793
|
|
|
4714
|
-
def populate_tf_resource_elasticsearch(self, spec):
|
|
4794
|
+
def populate_tf_resource_elasticsearch(self, spec: ExternalResourceSpec) -> None:
|
|
4715
4795
|
account = spec.provisioner_name
|
|
4716
4796
|
identifier = spec.identifier
|
|
4717
4797
|
values = self.init_values(spec)
|
|
4718
4798
|
output_prefix = spec.output_prefix
|
|
4719
4799
|
|
|
4720
|
-
tf_resources = []
|
|
4800
|
+
tf_resources: list[TFResource] = []
|
|
4721
4801
|
self.init_common_outputs(tf_resources, spec)
|
|
4722
4802
|
|
|
4723
4803
|
if not self.is_elasticsearch_domain_name_valid(values["identifier"]):
|
|
@@ -4730,10 +4810,11 @@ class TerrascriptClient:
|
|
|
4730
4810
|
)
|
|
4731
4811
|
|
|
4732
4812
|
tags = values["tags"]
|
|
4733
|
-
es_values = {
|
|
4734
|
-
|
|
4735
|
-
|
|
4736
|
-
|
|
4813
|
+
es_values: dict[str, Any] = {
|
|
4814
|
+
"domain_name": identifier,
|
|
4815
|
+
"tags": tags,
|
|
4816
|
+
"elasticsearch_version": values.get("elasticsearch_version"),
|
|
4817
|
+
}
|
|
4737
4818
|
|
|
4738
4819
|
(
|
|
4739
4820
|
log_group_resources,
|
|
@@ -4916,9 +4997,10 @@ class TerrascriptClient:
|
|
|
4916
4997
|
}
|
|
4917
4998
|
],
|
|
4918
4999
|
}
|
|
4919
|
-
es_values["access_policies"] =
|
|
5000
|
+
es_values["access_policies"] = json_dumps(access_policies)
|
|
4920
5001
|
|
|
4921
5002
|
region = values.get("region") or self.default_regions.get(account)
|
|
5003
|
+
assert region # make mypy happy
|
|
4922
5004
|
provider = ""
|
|
4923
5005
|
if self._multiregion_account(account):
|
|
4924
5006
|
provider = "aws." + region
|
|
@@ -4971,7 +5053,7 @@ class TerrascriptClient:
|
|
|
4971
5053
|
|
|
4972
5054
|
version_values = {
|
|
4973
5055
|
"secret_id": "${" + aws_secret_resource.id + "}",
|
|
4974
|
-
"secret_string":
|
|
5056
|
+
"secret_string": json_dumps(master_user),
|
|
4975
5057
|
}
|
|
4976
5058
|
if provider:
|
|
4977
5059
|
version_values["provider"] = provider
|
|
@@ -4998,7 +5080,7 @@ class TerrascriptClient:
|
|
|
4998
5080
|
iam_policy_resource = aws_iam_policy(
|
|
4999
5081
|
secret_identifier,
|
|
5000
5082
|
name=f"{identifier}-secretsmanager-policy",
|
|
5001
|
-
policy=
|
|
5083
|
+
policy=json_dumps(policy),
|
|
5002
5084
|
tags=tags,
|
|
5003
5085
|
)
|
|
5004
5086
|
tf_resources.append(iam_policy_resource)
|
|
@@ -5057,8 +5139,8 @@ class TerrascriptClient:
|
|
|
5057
5139
|
|
|
5058
5140
|
# TODO: @fishi0x01 remove this function after migration APPSRE-3409
|
|
5059
5141
|
def _build_es_advanced_security_options_deprecated(
|
|
5060
|
-
self, advanced_security_options:
|
|
5061
|
-
) ->
|
|
5142
|
+
self, advanced_security_options: dict[str, Any]
|
|
5143
|
+
) -> dict[str, Any]:
|
|
5062
5144
|
master_user_options = advanced_security_options.pop("master_user_options", {})
|
|
5063
5145
|
|
|
5064
5146
|
if master_user_options:
|
|
@@ -5079,13 +5161,13 @@ class TerrascriptClient:
|
|
|
5079
5161
|
|
|
5080
5162
|
return advanced_security_options
|
|
5081
5163
|
|
|
5082
|
-
def populate_tf_resource_acm(self, spec):
|
|
5164
|
+
def populate_tf_resource_acm(self, spec: ExternalResourceSpec) -> None:
|
|
5083
5165
|
account = spec.provisioner_name
|
|
5084
5166
|
identifier = spec.identifier
|
|
5085
5167
|
common_values = self.init_values(spec)
|
|
5086
5168
|
output_prefix = spec.output_prefix
|
|
5087
5169
|
|
|
5088
|
-
tf_resources = []
|
|
5170
|
+
tf_resources: list[TFResource] = []
|
|
5089
5171
|
self.init_common_outputs(tf_resources, spec)
|
|
5090
5172
|
|
|
5091
5173
|
values = {}
|
|
@@ -5124,6 +5206,7 @@ class TerrascriptClient:
|
|
|
5124
5206
|
values["subject_alternative_names"] = alt_names
|
|
5125
5207
|
|
|
5126
5208
|
region = common_values.get("region") or self.default_regions.get(account)
|
|
5209
|
+
assert region # make mypy happy
|
|
5127
5210
|
if self._multiregion_account(account):
|
|
5128
5211
|
values["provider"] = "aws." + region
|
|
5129
5212
|
|
|
@@ -5165,13 +5248,15 @@ class TerrascriptClient:
|
|
|
5165
5248
|
|
|
5166
5249
|
self.add_resources(account, tf_resources)
|
|
5167
5250
|
|
|
5168
|
-
def populate_tf_resource_s3_cloudfront_public_key(
|
|
5251
|
+
def populate_tf_resource_s3_cloudfront_public_key(
|
|
5252
|
+
self, spec: ExternalResourceSpec
|
|
5253
|
+
) -> None:
|
|
5169
5254
|
account = spec.provisioner_name
|
|
5170
5255
|
identifier = spec.identifier
|
|
5171
5256
|
common_values = self.init_values(spec)
|
|
5172
5257
|
output_prefix = spec.output_prefix
|
|
5173
5258
|
|
|
5174
|
-
tf_resources = []
|
|
5259
|
+
tf_resources: list[TFResource] = []
|
|
5175
5260
|
self.init_common_outputs(tf_resources, spec)
|
|
5176
5261
|
|
|
5177
5262
|
values = {"name": identifier, "comment": "managed by app-interface"}
|
|
@@ -5213,8 +5298,13 @@ class TerrascriptClient:
|
|
|
5213
5298
|
self.add_resources(account, tf_resources)
|
|
5214
5299
|
|
|
5215
5300
|
def _get_alb_target_ips_by_openshift_service(
|
|
5216
|
-
self,
|
|
5217
|
-
|
|
5301
|
+
self,
|
|
5302
|
+
identifier: str,
|
|
5303
|
+
openshift_service: str,
|
|
5304
|
+
account_name: str,
|
|
5305
|
+
namespace_info: Mapping[str, Any],
|
|
5306
|
+
ocm_map: OCMMap,
|
|
5307
|
+
) -> set[str]:
|
|
5218
5308
|
account = self.accounts[account_name]
|
|
5219
5309
|
cluster = namespace_info["cluster"]
|
|
5220
5310
|
ocm = ocm_map.get(cluster["name"])
|
|
@@ -5240,17 +5330,24 @@ class TerrascriptClient:
|
|
|
5240
5330
|
return ips
|
|
5241
5331
|
|
|
5242
5332
|
@staticmethod
|
|
5243
|
-
def _get_alb_rule_condition_value(
|
|
5333
|
+
def _get_alb_rule_condition_value(
|
|
5334
|
+
condition: Mapping[str, Any],
|
|
5335
|
+
) -> dict[str, dict[str, str]]:
|
|
5244
5336
|
condition_type = condition["type"]
|
|
5245
5337
|
condition_type_key = SUPPORTED_ALB_LISTENER_RULE_CONDITION_TYPE_MAPPING.get(
|
|
5246
5338
|
condition_type
|
|
5247
5339
|
)
|
|
5248
5340
|
if condition_type_key is None:
|
|
5249
5341
|
raise KeyError(f"unknown alb rule condition type {condition_type}")
|
|
5342
|
+
|
|
5343
|
+
# Query string conditions use a different structure than other condition types
|
|
5344
|
+
if condition_type == "query-string":
|
|
5345
|
+
return {condition_type_key: condition[condition_type_key]}
|
|
5346
|
+
|
|
5250
5347
|
return {condition_type_key: {"values": condition[condition_type_key]}}
|
|
5251
5348
|
|
|
5252
5349
|
@staticmethod
|
|
5253
|
-
def _get_principal_for_s3_bucket_policy(region: str) ->
|
|
5350
|
+
def _get_principal_for_s3_bucket_policy(region: str) -> dict[str, str]:
|
|
5254
5351
|
if region in AWS_ELB_ACCOUNT_IDS:
|
|
5255
5352
|
return {"AWS": f"arn:aws:iam::{AWS_ELB_ACCOUNT_IDS[region]}:root"}
|
|
5256
5353
|
if region in AWS_US_GOV_ELB_ACCOUNT_IDS:
|
|
@@ -5259,16 +5356,18 @@ class TerrascriptClient:
|
|
|
5259
5356
|
}
|
|
5260
5357
|
return {"Service": "logdelivery.elasticloadbalancing.amazonaws.com"}
|
|
5261
5358
|
|
|
5262
|
-
def populate_tf_resource_alb(
|
|
5359
|
+
def populate_tf_resource_alb(
|
|
5360
|
+
self, spec: ExternalResourceSpec, ocm_map: OCMMap | None = None
|
|
5361
|
+
) -> None:
|
|
5263
5362
|
account = spec.provisioner_name
|
|
5264
5363
|
identifier = spec.identifier
|
|
5265
5364
|
common_values = self.init_values(spec)
|
|
5266
5365
|
output_prefix = spec.output_prefix
|
|
5267
|
-
tf_resources = []
|
|
5366
|
+
tf_resources: list[TFResource] = []
|
|
5268
5367
|
namespace_info = spec.namespace
|
|
5269
5368
|
self.init_common_outputs(tf_resources, spec)
|
|
5270
5369
|
|
|
5271
|
-
default_region = self.default_regions
|
|
5370
|
+
default_region = self.default_regions[account]
|
|
5272
5371
|
cluster_region = namespace_info["cluster"]["spec"]["region"]
|
|
5273
5372
|
|
|
5274
5373
|
if self._multiregion_account(account):
|
|
@@ -5393,7 +5492,7 @@ class TerrascriptClient:
|
|
|
5393
5492
|
lb_access_logs_s3_bucket_policy_values = {
|
|
5394
5493
|
"provider": provider,
|
|
5395
5494
|
"bucket": f"${{{lb_access_logs_s3_bucket_tf_resource.id}}}",
|
|
5396
|
-
"policy":
|
|
5495
|
+
"policy": json_dumps(policy),
|
|
5397
5496
|
}
|
|
5398
5497
|
lb_access_logs_s3_bucket_policy_tf_resource = aws_s3_bucket_policy(
|
|
5399
5498
|
policy_identifier, **lb_access_logs_s3_bucket_policy_values
|
|
@@ -5421,6 +5520,10 @@ class TerrascriptClient:
|
|
|
5421
5520
|
t_protocol_version = t.get("protocol_version") or "HTTP1"
|
|
5422
5521
|
|
|
5423
5522
|
if t_openshift_service:
|
|
5523
|
+
if ocm_map is None:
|
|
5524
|
+
raise ValueError(
|
|
5525
|
+
"ocm_map should be not none raising exception to make mypy happy"
|
|
5526
|
+
)
|
|
5424
5527
|
target_ips = self._get_alb_target_ips_by_openshift_service(
|
|
5425
5528
|
identifier, t_openshift_service, account, namespace_info, ocm_map
|
|
5426
5529
|
)
|
|
@@ -5593,7 +5696,7 @@ class TerrascriptClient:
|
|
|
5593
5696
|
for rule_num, rule in enumerate(resource["rules"]):
|
|
5594
5697
|
# https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lb_listener_rule#type
|
|
5595
5698
|
action = rule["action"]
|
|
5596
|
-
action_values = {}
|
|
5699
|
+
action_values: dict[str, Any] = {}
|
|
5597
5700
|
action_type = action.get("type")
|
|
5598
5701
|
if action_type == "forward":
|
|
5599
5702
|
action_values = {
|
|
@@ -5679,18 +5782,19 @@ class TerrascriptClient:
|
|
|
5679
5782
|
|
|
5680
5783
|
self.add_resources(account, tf_resources)
|
|
5681
5784
|
|
|
5682
|
-
def populate_tf_resource_secrets_manager(self, spec):
|
|
5785
|
+
def populate_tf_resource_secrets_manager(self, spec: ExternalResourceSpec) -> None:
|
|
5683
5786
|
account = spec.provisioner_name
|
|
5684
5787
|
identifier = spec.identifier
|
|
5685
5788
|
common_values = self.init_values(spec)
|
|
5686
5789
|
output_prefix = spec.output_prefix
|
|
5687
5790
|
|
|
5688
|
-
tf_resources = []
|
|
5791
|
+
tf_resources: list[TFResource] = []
|
|
5689
5792
|
self.init_common_outputs(tf_resources, spec)
|
|
5690
5793
|
|
|
5691
5794
|
values = {"name": identifier}
|
|
5692
5795
|
|
|
5693
5796
|
region = common_values.get("region") or self.default_regions.get(account)
|
|
5797
|
+
assert region # make mypy happy
|
|
5694
5798
|
if self._multiregion_account(account):
|
|
5695
5799
|
values["provider"] = "aws." + region
|
|
5696
5800
|
|
|
@@ -5698,11 +5802,16 @@ class TerrascriptClient:
|
|
|
5698
5802
|
tf_resources.append(aws_secret_resource)
|
|
5699
5803
|
|
|
5700
5804
|
secret = common_values.get("secret")
|
|
5805
|
+
assert secret # make mypy happy
|
|
5701
5806
|
secret_data = self.secret_reader.read_all(secret)
|
|
5702
5807
|
|
|
5703
|
-
|
|
5808
|
+
secret_format = common_values.get("secret_format")
|
|
5809
|
+
if secret_format is not None:
|
|
5810
|
+
secret_data = self._apply_secret_format(str(secret_format), secret_data)
|
|
5811
|
+
|
|
5812
|
+
version_values: dict[str, Any] = {
|
|
5704
5813
|
"secret_id": "${" + aws_secret_resource.id + "}",
|
|
5705
|
-
"secret_string":
|
|
5814
|
+
"secret_string": json_dumps(secret_data),
|
|
5706
5815
|
}
|
|
5707
5816
|
|
|
5708
5817
|
if self._multiregion_account(account):
|
|
@@ -5723,6 +5832,66 @@ class TerrascriptClient:
|
|
|
5723
5832
|
|
|
5724
5833
|
self.add_resources(account, tf_resources)
|
|
5725
5834
|
|
|
5835
|
+
@staticmethod
|
|
5836
|
+
def _unflatten_dotted_keys_dict(flat_dict: dict[str, str]) -> dict[str, Any]:
|
|
5837
|
+
"""Convert a flat dictionary with dotted keys to a nested dictionary.
|
|
5838
|
+
|
|
5839
|
+
Example:
|
|
5840
|
+
{"db.host": "localhost", "db.port": "5432"} ->
|
|
5841
|
+
{"db": {"host": "localhost", "port": "5432"}}
|
|
5842
|
+
|
|
5843
|
+
Raises:
|
|
5844
|
+
ValueError: If there are conflicting keys (e.g., "a.b" and "a.b.c")
|
|
5845
|
+
"""
|
|
5846
|
+
result: dict[str, Any] = {}
|
|
5847
|
+
for key, value in flat_dict.items():
|
|
5848
|
+
parts = key.split(".")
|
|
5849
|
+
current = result
|
|
5850
|
+
for i, part in enumerate(parts[:-1]):
|
|
5851
|
+
if part not in current:
|
|
5852
|
+
current[part] = {}
|
|
5853
|
+
elif not isinstance(current[part], dict):
|
|
5854
|
+
# Conflict: trying to traverse through a non-dict value
|
|
5855
|
+
conflicting_path = ".".join(parts[: i + 1])
|
|
5856
|
+
raise ValueError(
|
|
5857
|
+
f"Conflicting keys detected: '{conflicting_path}' is both a "
|
|
5858
|
+
f"value and a nested path in key '{key}'"
|
|
5859
|
+
)
|
|
5860
|
+
current = current[part]
|
|
5861
|
+
|
|
5862
|
+
# Check if we're trying to set a value where a dict already exists
|
|
5863
|
+
if parts[-1] in current and isinstance(current[parts[-1]], dict):
|
|
5864
|
+
raise ValueError(
|
|
5865
|
+
f"Conflicting keys detected: '{key}' conflicts with nested keys"
|
|
5866
|
+
)
|
|
5867
|
+
|
|
5868
|
+
current[parts[-1]] = value
|
|
5869
|
+
|
|
5870
|
+
return result
|
|
5871
|
+
|
|
5872
|
+
@staticmethod
|
|
5873
|
+
def _apply_secret_format(
|
|
5874
|
+
secret_format: str, secret_data: dict[str, str]
|
|
5875
|
+
) -> dict[str, str]:
|
|
5876
|
+
# Convert flat dict with dotted keys to nested dict for Jinja2
|
|
5877
|
+
nested_secret_data = TerrascriptClient._unflatten_dotted_keys_dict(secret_data)
|
|
5878
|
+
rendered_data = process_jinja2_template(secret_format, nested_secret_data)
|
|
5879
|
+
|
|
5880
|
+
parsed_data = json.loads(rendered_data)
|
|
5881
|
+
|
|
5882
|
+
if not isinstance(parsed_data, dict):
|
|
5883
|
+
raise ValueError("secret_format must be a dictionary")
|
|
5884
|
+
|
|
5885
|
+
# validate secret is a dict[str, str]
|
|
5886
|
+
for k, v in parsed_data.items():
|
|
5887
|
+
if not isinstance(k, str):
|
|
5888
|
+
raise ValueError(f"key '{k}' is not a string")
|
|
5889
|
+
|
|
5890
|
+
if not isinstance(v, str):
|
|
5891
|
+
raise ValueError(f"dictionary value '{v}' under '{k}' is not a string")
|
|
5892
|
+
|
|
5893
|
+
return parsed_data
|
|
5894
|
+
|
|
5726
5895
|
def get_commit_sha(self, repo_info: Mapping) -> str:
|
|
5727
5896
|
url = repo_info["url"]
|
|
5728
5897
|
ref = repo_info["ref"]
|
|
@@ -5741,7 +5910,8 @@ class TerrascriptClient:
|
|
|
5741
5910
|
return commit.sha
|
|
5742
5911
|
case "gitlab":
|
|
5743
5912
|
gitlab = self.init_gitlab()
|
|
5744
|
-
project
|
|
5913
|
+
if not (project := gitlab.get_project(url)):
|
|
5914
|
+
raise ValueError(f"could not find gitlab project for url {url}")
|
|
5745
5915
|
commits = project.commits.list(ref_name=ref, per_page=1, page=1)
|
|
5746
5916
|
return commits[0].id
|
|
5747
5917
|
case _:
|
|
@@ -5781,7 +5951,7 @@ class TerrascriptClient:
|
|
|
5781
5951
|
return True
|
|
5782
5952
|
return False
|
|
5783
5953
|
|
|
5784
|
-
def populate_tf_resource_asg(self, spec) -> None:
|
|
5954
|
+
def populate_tf_resource_asg(self, spec: ExternalResourceSpec) -> None:
|
|
5785
5955
|
account = spec.provisioner_name
|
|
5786
5956
|
identifier = spec.identifier
|
|
5787
5957
|
common_values = self.init_values(spec)
|
|
@@ -5868,7 +6038,7 @@ class TerrascriptClient:
|
|
|
5868
6038
|
template_resource = aws_launch_template(identifier, **template_values)
|
|
5869
6039
|
tf_resources.append(template_resource)
|
|
5870
6040
|
|
|
5871
|
-
asg_value = {
|
|
6041
|
+
asg_value: dict[str, Any] = {
|
|
5872
6042
|
"name": identifier,
|
|
5873
6043
|
"max_size": common_values.get("max_size"),
|
|
5874
6044
|
"min_size": common_values.get("min_size"),
|
|
@@ -5924,12 +6094,12 @@ class TerrascriptClient:
|
|
|
5924
6094
|
|
|
5925
6095
|
self.add_resources(account, tf_resources)
|
|
5926
6096
|
|
|
5927
|
-
def populate_tf_resource_route53_zone(self, spec):
|
|
6097
|
+
def populate_tf_resource_route53_zone(self, spec: ExternalResourceSpec) -> None:
|
|
5928
6098
|
account = spec.provisioner_name
|
|
5929
6099
|
identifier = spec.identifier
|
|
5930
6100
|
common_values = self.init_values(spec)
|
|
5931
6101
|
output_prefix = spec.output_prefix
|
|
5932
|
-
tf_resources = []
|
|
6102
|
+
tf_resources: list[TFResource] = []
|
|
5933
6103
|
self.init_common_outputs(tf_resources, spec)
|
|
5934
6104
|
|
|
5935
6105
|
# https://www.terraform.io/docs/providers/aws/r/route53_zone.html
|
|
@@ -5973,16 +6143,20 @@ class TerrascriptClient:
|
|
|
5973
6143
|
|
|
5974
6144
|
self.add_resources(account, tf_resources)
|
|
5975
6145
|
|
|
5976
|
-
def populate_tf_resource_rosa_authenticator(
|
|
6146
|
+
def populate_tf_resource_rosa_authenticator(
|
|
6147
|
+
self, spec: ExternalResourceSpec
|
|
6148
|
+
) -> None:
|
|
5977
6149
|
account = spec.provisioner_name
|
|
5978
6150
|
identifier = spec.identifier
|
|
5979
6151
|
common_values = self.init_values(spec)
|
|
5980
|
-
tf_resources = []
|
|
6152
|
+
tf_resources: list[TFResource] = []
|
|
5981
6153
|
self.init_common_outputs(tf_resources, spec)
|
|
5982
6154
|
|
|
5983
6155
|
# Prepare consts
|
|
5984
6156
|
region = common_values.get("region") or self.default_regions.get(account)
|
|
6157
|
+
assert region # make mypy happy
|
|
5985
6158
|
bucket_name = common_values.get("cognito_callback_bucket_name")
|
|
6159
|
+
assert bucket_name # make mypy happy
|
|
5986
6160
|
bucket_url = f"https://{bucket_name}.s3.{region}.amazonaws.com"
|
|
5987
6161
|
lambda_managed_policy_arn = (
|
|
5988
6162
|
"arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
|
|
@@ -5992,6 +6166,7 @@ class TerrascriptClient:
|
|
|
5992
6166
|
vpc_id = common_values.get("vpc_id")
|
|
5993
6167
|
subnet_ids = common_values.get("subnet_ids")
|
|
5994
6168
|
network_interface_ids = common_values.get("network_interface_ids")
|
|
6169
|
+
assert network_interface_ids is not None # make mypy happy
|
|
5995
6170
|
certificate_arn = common_values.get("certificate_arn")
|
|
5996
6171
|
domain_name = common_values.get("domain_name")
|
|
5997
6172
|
openshift_ingress_load_balancer_arn = common_values.get(
|
|
@@ -6017,7 +6192,7 @@ class TerrascriptClient:
|
|
|
6017
6192
|
lambda_iam_role_resource = aws_iam_role(
|
|
6018
6193
|
"lambda_role",
|
|
6019
6194
|
name=f"ocm-{identifier}-cognito-lambda-role",
|
|
6020
|
-
assume_role_policy=
|
|
6195
|
+
assume_role_policy=json_dumps(lambda_role_policy),
|
|
6021
6196
|
managed_policy_arns=[lambda_managed_policy_arn],
|
|
6022
6197
|
force_detach_policies=False,
|
|
6023
6198
|
max_session_duration=3600,
|
|
@@ -6692,7 +6867,7 @@ class TerrascriptClient:
|
|
|
6692
6867
|
)
|
|
6693
6868
|
tf_resources.append(api_gateway_stage_resource)
|
|
6694
6869
|
|
|
6695
|
-
rest_api_policy =
|
|
6870
|
+
rest_api_policy = json_dumps({
|
|
6696
6871
|
"Version": "2012-10-17",
|
|
6697
6872
|
"Statement": [
|
|
6698
6873
|
{
|
|
@@ -6796,7 +6971,7 @@ class TerrascriptClient:
|
|
|
6796
6971
|
},
|
|
6797
6972
|
],
|
|
6798
6973
|
}
|
|
6799
|
-
cloudwatch_assume_role_policy =
|
|
6974
|
+
cloudwatch_assume_role_policy = json_dumps(policy)
|
|
6800
6975
|
|
|
6801
6976
|
cloudwatch_iam_role_resource = aws_iam_role(
|
|
6802
6977
|
"cloudwatch_assume_role",
|
|
@@ -6824,7 +6999,7 @@ class TerrascriptClient:
|
|
|
6824
6999
|
],
|
|
6825
7000
|
}
|
|
6826
7001
|
|
|
6827
|
-
cloudwatch_iam_policy_document =
|
|
7002
|
+
cloudwatch_iam_policy_document = json_dumps(policy)
|
|
6828
7003
|
|
|
6829
7004
|
cloudwatch_iam_policy_resource = aws_iam_policy(
|
|
6830
7005
|
"cloudwatch",
|
|
@@ -6868,15 +7043,18 @@ class TerrascriptClient:
|
|
|
6868
7043
|
|
|
6869
7044
|
self.add_resources(account, tf_resources)
|
|
6870
7045
|
|
|
6871
|
-
def populate_tf_resource_rosa_authenticator_vpce(
|
|
7046
|
+
def populate_tf_resource_rosa_authenticator_vpce(
|
|
7047
|
+
self, spec: ExternalResourceSpec
|
|
7048
|
+
) -> None:
|
|
6872
7049
|
account = spec.provisioner_name
|
|
6873
7050
|
identifier = spec.identifier
|
|
6874
7051
|
common_values = self.init_values(spec)
|
|
6875
|
-
tf_resources = []
|
|
7052
|
+
tf_resources: list[TFResource] = []
|
|
6876
7053
|
self.init_common_outputs(tf_resources, spec)
|
|
6877
7054
|
|
|
6878
7055
|
vpc_id = common_values.get("vpc_id")
|
|
6879
7056
|
subnet_ids = common_values.get("subnet_ids")
|
|
7057
|
+
assert subnet_ids is not None # make mypy happy
|
|
6880
7058
|
vpce_security_group_rule_common_args = common_values.get(
|
|
6881
7059
|
"vpce_security_group_rule_common_properties", None
|
|
6882
7060
|
)
|
|
@@ -6935,11 +7113,11 @@ class TerrascriptClient:
|
|
|
6935
7113
|
|
|
6936
7114
|
self.add_resources(account, tf_resources)
|
|
6937
7115
|
|
|
6938
|
-
def populate_tf_resource_msk(self, spec):
|
|
7116
|
+
def populate_tf_resource_msk(self, spec: ExternalResourceSpec) -> None:
|
|
6939
7117
|
account = spec.provisioner_name
|
|
6940
7118
|
values = self.init_values(spec)
|
|
6941
7119
|
output_prefix = spec.output_prefix
|
|
6942
|
-
tf_resources = []
|
|
7120
|
+
tf_resources: list[TFResource] = []
|
|
6943
7121
|
resource_id = spec.identifier
|
|
6944
7122
|
|
|
6945
7123
|
del values["identifier"]
|
|
@@ -7066,7 +7244,7 @@ class TerrascriptClient:
|
|
|
7066
7244
|
|
|
7067
7245
|
version_values = {
|
|
7068
7246
|
"secret_id": "${" + secret_resource.arn + "}",
|
|
7069
|
-
"secret_string":
|
|
7247
|
+
"secret_string": json_dumps(secret),
|
|
7070
7248
|
}
|
|
7071
7249
|
version_resource = aws_secretsmanager_secret_version(
|
|
7072
7250
|
secret_identifier, **version_values
|
|
@@ -7075,7 +7253,7 @@ class TerrascriptClient:
|
|
|
7075
7253
|
|
|
7076
7254
|
secret_policy_values = {
|
|
7077
7255
|
"secret_arn": "${" + secret_resource.arn + "}",
|
|
7078
|
-
"policy":
|
|
7256
|
+
"policy": json_dumps({
|
|
7079
7257
|
"Version": "2012-10-17",
|
|
7080
7258
|
"Statement": [
|
|
7081
7259
|
{
|