qontract-reconcile 0.10.2.dev394__py3-none-any.whl → 0.10.2.dev414__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.dev394.dist-info → qontract_reconcile-0.10.2.dev414.dist-info}/METADATA +4 -3
- {qontract_reconcile-0.10.2.dev394.dist-info → qontract_reconcile-0.10.2.dev414.dist-info}/RECORD +308 -308
- reconcile/acs_rbac.py +2 -2
- reconcile/aus/advanced_upgrade_service.py +15 -12
- reconcile/aus/base.py +9 -13
- reconcile/aus/cluster_version_data.py +15 -5
- reconcile/aus/models.py +1 -1
- reconcile/automated_actions/config/integration.py +15 -3
- reconcile/aws_account_manager/integration.py +6 -6
- reconcile/aws_account_manager/reconciler.py +3 -3
- reconcile/aws_ami_cleanup/integration.py +2 -5
- reconcile/aws_ami_share.py +69 -62
- reconcile/aws_saml_idp/integration.py +5 -3
- reconcile/aws_saml_roles/integration.py +23 -22
- reconcile/aws_version_sync/integration.py +6 -12
- reconcile/change_owners/bundle.py +3 -3
- reconcile/change_owners/change_log_tracking.py +3 -2
- reconcile/change_owners/change_owners.py +1 -1
- reconcile/dashdotdb_dora.py +1 -1
- reconcile/dashdotdb_slo.py +1 -1
- reconcile/database_access_manager.py +8 -9
- 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 +1 -1
- reconcile/external_resources/integration.py +1 -1
- reconcile/external_resources/manager.py +19 -7
- reconcile/external_resources/metrics.py +1 -1
- reconcile/external_resources/model.py +6 -6
- reconcile/external_resources/reconciler.py +7 -4
- reconcile/external_resources/secrets_sync.py +2 -2
- reconcile/external_resources/state.py +56 -14
- reconcile/fleet_labeler/integration.py +1 -1
- reconcile/gcp_image_mirror.py +2 -2
- reconcile/github_org.py +1 -1
- reconcile/github_owners.py +4 -0
- reconcile/gitlab_members.py +6 -12
- reconcile/gitlab_permissions.py +8 -12
- reconcile/glitchtip_project_alerts/integration.py +3 -1
- reconcile/gql_definitions/acs/acs_instances.py +5 -5
- reconcile/gql_definitions/acs/acs_policies.py +5 -5
- reconcile/gql_definitions/acs/acs_rbac.py +5 -5
- reconcile/gql_definitions/advanced_upgrade_service/aus_clusters.py +5 -5
- reconcile/gql_definitions/advanced_upgrade_service/aus_organization.py +5 -5
- reconcile/gql_definitions/app_interface_metrics_exporter/onboarding_status.py +5 -5
- 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 +46 -7
- reconcile/gql_definitions/aws_account_manager/aws_accounts.py +5 -5
- reconcile/gql_definitions/aws_ami_cleanup/aws_accounts.py +5 -5
- reconcile/gql_definitions/aws_cloudwatch_log_retention/aws_accounts.py +5 -5
- reconcile/gql_definitions/aws_saml_idp/aws_accounts.py +5 -5
- reconcile/gql_definitions/aws_saml_roles/aws_accounts.py +5 -5
- reconcile/gql_definitions/aws_saml_roles/roles.py +5 -5
- reconcile/gql_definitions/aws_version_sync/clusters.py +5 -5
- 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 +5 -5
- reconcile/gql_definitions/cluster_auth_rhidp/clusters.py +5 -5
- reconcile/gql_definitions/common/alerting_services_settings.py +5 -5
- 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 +5 -5
- reconcile/gql_definitions/common/app_interface_state_settings.py +5 -5
- 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 +5 -5
- reconcile/gql_definitions/common/aws_vpcs.py +5 -5
- reconcile/gql_definitions/common/clusters.py +5 -5
- reconcile/gql_definitions/common/clusters_minimal.py +5 -5
- reconcile/gql_definitions/common/clusters_with_dms.py +5 -5
- reconcile/gql_definitions/common/clusters_with_peering.py +5 -5
- reconcile/gql_definitions/common/github_orgs.py +5 -5
- reconcile/gql_definitions/common/jira_settings.py +5 -5
- reconcile/gql_definitions/common/jiralert_settings.py +5 -5
- reconcile/gql_definitions/common/ldap_settings.py +5 -5
- reconcile/gql_definitions/common/namespaces.py +5 -5
- reconcile/gql_definitions/common/namespaces_minimal.py +7 -5
- reconcile/gql_definitions/common/ocm_env_telemeter.py +5 -5
- reconcile/gql_definitions/common/ocm_environments.py +5 -5
- reconcile/gql_definitions/common/pagerduty_instances.py +5 -5
- reconcile/gql_definitions/common/pgp_reencryption_settings.py +5 -5
- reconcile/gql_definitions/common/pipeline_providers.py +5 -5
- 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 +5 -5
- reconcile/gql_definitions/common/saas_target_namespaces.py +5 -5
- 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 +5 -5
- reconcile/gql_definitions/common/state_aws_account.py +5 -5
- 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 +5 -5
- reconcile/gql_definitions/dashdotdb_slo/slo_documents_query.py +5 -5
- reconcile/gql_definitions/dynatrace_token_provider/dynatrace_bootstrap_tokens.py +5 -5
- 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 +5 -5
- reconcile/gql_definitions/email_sender/users.py +5 -5
- reconcile/gql_definitions/endpoints_discovery/apps.py +5 -5
- reconcile/gql_definitions/external_resources/aws_accounts.py +5 -5
- reconcile/gql_definitions/external_resources/external_resources_modules.py +5 -5
- reconcile/gql_definitions/external_resources/external_resources_namespaces.py +5 -5
- reconcile/gql_definitions/external_resources/external_resources_settings.py +5 -5
- reconcile/gql_definitions/external_resources/fragments/external_resources_module_overrides.py +5 -5
- reconcile/gql_definitions/fleet_labeler/fleet_labels.py +5 -5
- reconcile/gql_definitions/fragments/aus_organization.py +5 -5
- reconcile/gql_definitions/fragments/aws_account_common.py +5 -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_organization.py +5 -5
- reconcile/gql_definitions/fragments/aws_vpc.py +5 -5
- reconcile/gql_definitions/fragments/aws_vpc_request.py +5 -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 +5 -5
- reconcile/gql_definitions/gcp/gcp_projects.py +5 -5
- reconcile/gql_definitions/gitlab_members/gitlab_instances.py +5 -5
- reconcile/gql_definitions/gitlab_members/permissions.py +5 -5
- reconcile/gql_definitions/glitchtip/glitchtip_instance.py +5 -5
- reconcile/gql_definitions/glitchtip/glitchtip_project.py +5 -5
- reconcile/gql_definitions/glitchtip_project_alerts/glitchtip_project.py +5 -5
- reconcile/gql_definitions/integrations/integrations.py +5 -5
- reconcile/gql_definitions/introspection.json +231 -0
- reconcile/gql_definitions/jenkins_configs/jenkins_configs.py +5 -5
- reconcile/gql_definitions/jenkins_configs/jenkins_instances.py +5 -5
- reconcile/gql_definitions/jira/jira_servers.py +5 -5
- reconcile/gql_definitions/jira_permissions_validator/jira_boards_for_permissions_validator.py +5 -5
- reconcile/gql_definitions/jumphosts/jumphosts.py +5 -5
- reconcile/gql_definitions/ldap_groups/roles.py +5 -5
- reconcile/gql_definitions/ldap_groups/settings.py +5 -5
- reconcile/gql_definitions/maintenance/maintenances.py +5 -5
- reconcile/gql_definitions/membershipsources/roles.py +5 -5
- reconcile/gql_definitions/ocm_labels/clusters.py +5 -5
- reconcile/gql_definitions/ocm_labels/organizations.py +5 -5
- reconcile/gql_definitions/openshift_cluster_bots/clusters.py +5 -5
- reconcile/gql_definitions/openshift_groups/managed_groups.py +5 -5
- reconcile/gql_definitions/openshift_groups/managed_roles.py +5 -5
- reconcile/gql_definitions/openshift_serviceaccount_tokens/tokens.py +5 -5
- reconcile/gql_definitions/quay_membership/quay_membership.py +5 -5
- reconcile/gql_definitions/rhcs/certs.py +5 -5
- reconcile/gql_definitions/rhidp/organizations.py +5 -5
- reconcile/gql_definitions/service_dependencies/jenkins_instance_fragment.py +5 -5
- reconcile/gql_definitions/service_dependencies/service_dependencies.py +5 -5
- reconcile/gql_definitions/sharding/aws_accounts.py +5 -5
- reconcile/gql_definitions/sharding/ocm_organization.py +5 -5
- reconcile/gql_definitions/skupper_network/site_controller_template.py +5 -5
- reconcile/gql_definitions/skupper_network/skupper_networks.py +5 -5
- reconcile/gql_definitions/slack_usergroups/clusters.py +5 -5
- reconcile/gql_definitions/slack_usergroups/permissions.py +5 -5
- 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 +5 -5
- reconcile/gql_definitions/statuspage/statuspages.py +5 -5
- 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 +5 -5
- reconcile/gql_definitions/terraform_cloudflare_dns/terraform_cloudflare_zones.py +5 -5
- reconcile/gql_definitions/terraform_cloudflare_resources/terraform_cloudflare_accounts.py +5 -5
- reconcile/gql_definitions/terraform_cloudflare_resources/terraform_cloudflare_resources.py +5 -5
- reconcile/gql_definitions/terraform_cloudflare_users/app_interface_setting_cloudflare_and_vault.py +5 -5
- reconcile/gql_definitions/terraform_cloudflare_users/terraform_cloudflare_roles.py +5 -5
- reconcile/gql_definitions/terraform_init/aws_accounts.py +5 -5
- reconcile/gql_definitions/terraform_repo/terraform_repo.py +5 -5
- reconcile/gql_definitions/terraform_resources/database_access_manager.py +5 -5
- reconcile/gql_definitions/terraform_resources/terraform_resources_namespaces.py +5 -5
- reconcile/gql_definitions/terraform_tgw_attachments/aws_accounts.py +5 -5
- reconcile/gql_definitions/unleash_feature_toggles/feature_toggles.py +5 -5
- reconcile/gql_definitions/vault_instances/vault_instances.py +5 -5
- reconcile/gql_definitions/vault_policies/vault_policies.py +5 -5
- reconcile/gql_definitions/vpc_peerings_validator/vpc_peerings_validator.py +5 -5
- reconcile/gql_definitions/vpc_peerings_validator/vpc_peerings_validator_peered_cluster_fragment.py +5 -5
- reconcile/integrations_manager.py +3 -3
- reconcile/jenkins_worker_fleets.py +9 -8
- reconcile/jira_permissions_validator.py +2 -2
- reconcile/ldap_groups/integration.py +1 -1
- reconcile/ocm/types.py +35 -57
- 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 +23 -23
- reconcile/openshift_base.py +53 -2
- reconcile/openshift_cluster_bots.py +1 -1
- reconcile/openshift_namespace_labels.py +1 -1
- reconcile/openshift_namespaces.py +97 -101
- reconcile/openshift_resources_base.py +6 -2
- reconcile/openshift_rhcs_certs.py +5 -5
- reconcile/openshift_rolebindings.py +7 -11
- reconcile/openshift_saas_deploy.py +4 -5
- reconcile/openshift_saas_deploy_change_tester.py +9 -7
- reconcile/openshift_serviceaccount_tokens.py +2 -2
- reconcile/openshift_upgrade_watcher.py +1 -1
- reconcile/oum/labelset.py +5 -3
- reconcile/oum/models.py +1 -4
- reconcile/prometheus_rules_tester/integration.py +3 -3
- reconcile/quay_mirror.py +1 -1
- reconcile/queries.py +6 -0
- reconcile/rhidp/common.py +3 -5
- reconcile/rhidp/sso_client/base.py +1 -1
- reconcile/saas_auto_promotions_manager/merge_request_manager/renderer.py +1 -1
- reconcile/skupper_network/integration.py +2 -2
- reconcile/slack_usergroups.py +31 -11
- reconcile/status_board.py +6 -6
- reconcile/statuspage/atlassian.py +7 -7
- reconcile/statuspage/page.py +4 -9
- reconcile/templating/lib/rendering.py +3 -3
- reconcile/templating/renderer.py +2 -2
- reconcile/terraform_cloudflare_dns.py +3 -3
- reconcile/terraform_cloudflare_resources.py +5 -5
- reconcile/terraform_cloudflare_users.py +3 -2
- reconcile/terraform_init/integration.py +2 -2
- reconcile/terraform_repo.py +16 -12
- reconcile/terraform_resources.py +6 -6
- reconcile/terraform_tgw_attachments.py +20 -18
- reconcile/terraform_vpc_resources/integration.py +3 -1
- 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 +11 -11
- 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/aws_api.py +51 -20
- reconcile/utils/aws_api_typed/organization.py +4 -2
- reconcile/utils/deadmanssnitch_api.py +1 -1
- reconcile/utils/early_exit_cache.py +8 -10
- reconcile/utils/gitlab_api.py +7 -5
- reconcile/utils/glitchtip/client.py +6 -2
- reconcile/utils/glitchtip/models.py +25 -28
- reconcile/utils/gql.py +4 -7
- reconcile/utils/instrumented_wrappers.py +1 -1
- reconcile/utils/internal_groups/client.py +2 -2
- reconcile/utils/internal_groups/models.py +8 -17
- reconcile/utils/jinja2/utils.py +2 -5
- reconcile/utils/jobcontroller/controller.py +1 -1
- reconcile/utils/jobcontroller/models.py +17 -1
- reconcile/utils/json.py +39 -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 +1 -1
- reconcile/utils/merge_request_manager/parser.py +4 -4
- reconcile/utils/metrics.py +5 -5
- reconcile/utils/models.py +304 -82
- reconcile/utils/mr/notificator.py +1 -1
- reconcile/utils/mr/user_maintenance.py +3 -2
- reconcile/utils/oc.py +112 -92
- reconcile/utils/ocm/addons.py +0 -1
- reconcile/utils/ocm/base.py +17 -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/products.py +8 -8
- reconcile/utils/ocm/service_log.py +1 -1
- reconcile/utils/ocm/sre_capability_labels.py +20 -13
- reconcile/utils/openshift_resource.py +5 -0
- reconcile/utils/pagerduty_api.py +5 -2
- reconcile/utils/promotion_state.py +6 -11
- reconcile/utils/raw_github_api.py +1 -1
- reconcile/utils/rhcsv2_certs.py +1 -4
- reconcile/utils/runtime/integration.py +1 -1
- reconcile/utils/saasherder/interfaces.py +13 -20
- reconcile/utils/saasherder/models.py +23 -20
- reconcile/utils/saasherder/saasherder.py +26 -17
- reconcile/utils/slack_api.py +2 -2
- reconcile/utils/structs.py +1 -1
- reconcile/utils/terraform_client.py +1 -1
- reconcile/utils/terrascript_aws_client.py +47 -43
- reconcile/utils/unleash/server.py +2 -8
- reconcile/utils/vault.py +4 -11
- reconcile/utils/vcs.py +8 -8
- reconcile/vault_replication.py +1 -1
- 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 +3 -1
- tools/qontract_cli.py +6 -5
- tools/template_validation.py +3 -1
- {qontract_reconcile-0.10.2.dev394.dist-info → qontract_reconcile-0.10.2.dev414.dist-info}/WHEEL +0 -0
- {qontract_reconcile-0.10.2.dev394.dist-info → qontract_reconcile-0.10.2.dev414.dist-info}/entry_points.txt +0 -0
reconcile/terraform_repo.py
CHANGED
|
@@ -41,10 +41,10 @@ class RepoOutput(BaseModel):
|
|
|
41
41
|
project_path: str
|
|
42
42
|
delete: bool
|
|
43
43
|
aws_creds: VaultSecret
|
|
44
|
-
variables: TerraformRepoVariablesV1 | None
|
|
45
|
-
bucket: str | None
|
|
46
|
-
region: str | None
|
|
47
|
-
bucket_path: str | None
|
|
44
|
+
variables: TerraformRepoVariablesV1 | None = None
|
|
45
|
+
bucket: str | None = None
|
|
46
|
+
region: str | None = None
|
|
47
|
+
bucket_path: str | None = None
|
|
48
48
|
require_fips: bool
|
|
49
49
|
tf_version: str
|
|
50
50
|
|
|
@@ -62,8 +62,8 @@ class OutputFile(BaseModel):
|
|
|
62
62
|
class TerraformRepoIntegrationParams(PydanticRunParams):
|
|
63
63
|
output_file: str | None
|
|
64
64
|
validate_git: bool
|
|
65
|
-
gitlab_project_id: str | None
|
|
66
|
-
gitlab_merge_request_id: int | None
|
|
65
|
+
gitlab_project_id: str | None = None
|
|
66
|
+
gitlab_merge_request_id: int | None = None
|
|
67
67
|
|
|
68
68
|
|
|
69
69
|
class TerraformRepoIntegration(
|
|
@@ -168,7 +168,7 @@ class TerraformRepoIntegration(
|
|
|
168
168
|
self.params.output_file, "w", encoding="locale"
|
|
169
169
|
) as output_file:
|
|
170
170
|
yaml.safe_dump(
|
|
171
|
-
data=output.
|
|
171
|
+
data=output.model_dump(),
|
|
172
172
|
stream=output_file,
|
|
173
173
|
explicit_start=True,
|
|
174
174
|
)
|
|
@@ -177,7 +177,7 @@ class TerraformRepoIntegration(
|
|
|
177
177
|
f"Unable to write to '{self.params.output_file}'"
|
|
178
178
|
) from None
|
|
179
179
|
else:
|
|
180
|
-
print(yaml.safe_dump(data=output.
|
|
180
|
+
print(yaml.safe_dump(data=output.model_dump(), explicit_start=True))
|
|
181
181
|
|
|
182
182
|
return output
|
|
183
183
|
|
|
@@ -206,7 +206,7 @@ class TerraformRepoIntegration(
|
|
|
206
206
|
keys = state.ls()
|
|
207
207
|
for key in keys:
|
|
208
208
|
if value := state.get(key.lstrip("/"), None):
|
|
209
|
-
repo = TerraformRepoV1.
|
|
209
|
+
repo = TerraformRepoV1.model_validate(value)
|
|
210
210
|
repo_list.append(repo)
|
|
211
211
|
|
|
212
212
|
return repo_list
|
|
@@ -283,7 +283,7 @@ class TerraformRepoIntegration(
|
|
|
283
283
|
for add_key, add_val in diff_result.add.items():
|
|
284
284
|
# state.add already performs a json.dumps(key) so we export the
|
|
285
285
|
# pydantic model as a dict to avoid a double json dump with extra quotes
|
|
286
|
-
state.add(add_key, add_val.
|
|
286
|
+
state.add(add_key, add_val.model_dump(by_alias=True), force=True)
|
|
287
287
|
for delete_key in diff_result.delete:
|
|
288
288
|
state.rm(delete_key)
|
|
289
289
|
for change_key, change_val in diff_result.change.items():
|
|
@@ -291,7 +291,9 @@ class TerraformRepoIntegration(
|
|
|
291
291
|
state.rm(change_key)
|
|
292
292
|
else:
|
|
293
293
|
state.add(
|
|
294
|
-
change_key,
|
|
294
|
+
change_key,
|
|
295
|
+
change_val.desired.model_dump(by_alias=True),
|
|
296
|
+
force=True,
|
|
295
297
|
)
|
|
296
298
|
except KeyError:
|
|
297
299
|
pass
|
|
@@ -394,5 +396,7 @@ class TerraformRepoIntegration(
|
|
|
394
396
|
def early_exit_desired_state(self, *args: Any, **kwargs: Any) -> dict[str, Any]:
|
|
395
397
|
gqlapi = gql.get_api()
|
|
396
398
|
return {
|
|
397
|
-
"repos": [
|
|
399
|
+
"repos": [
|
|
400
|
+
repo.model_dump() for repo in self.get_repos(query_func=gqlapi.query)
|
|
401
|
+
]
|
|
398
402
|
}
|
reconcile/terraform_resources.py
CHANGED
|
@@ -137,7 +137,7 @@ def fetch_current_state(
|
|
|
137
137
|
use_jump_host=use_jump_host,
|
|
138
138
|
thread_pool_size=thread_pool_size,
|
|
139
139
|
)
|
|
140
|
-
namespaces_dicts = [ns.
|
|
140
|
+
namespaces_dicts = [ns.model_dump(by_alias=True) for ns in namespaces]
|
|
141
141
|
state_specs = ob.init_specs_to_fetch(
|
|
142
142
|
ri, oc_map, namespaces=namespaces_dicts, override_managed_types=["Secret"]
|
|
143
143
|
)
|
|
@@ -273,7 +273,7 @@ def setup(
|
|
|
273
273
|
)
|
|
274
274
|
else:
|
|
275
275
|
ocm_map = None
|
|
276
|
-
tf_namespaces_dicts = [ns.
|
|
276
|
+
tf_namespaces_dicts = [ns.model_dump(by_alias=True) for ns in tf_namespaces]
|
|
277
277
|
|
|
278
278
|
provider_exclusions = settings.get("terraformResourcesProviderExclusions") or []
|
|
279
279
|
ts.init_populate_specs(
|
|
@@ -295,16 +295,16 @@ def filter_tf_namespaces(
|
|
|
295
295
|
) -> list[NamespaceV1]:
|
|
296
296
|
tf_namespaces = []
|
|
297
297
|
for namespace_info in namespaces:
|
|
298
|
-
if ob.is_namespace_deleted(namespace_info.
|
|
298
|
+
if ob.is_namespace_deleted(namespace_info.model_dump(by_alias=True)):
|
|
299
299
|
continue
|
|
300
|
-
if not managed_external_resources(namespace_info.
|
|
300
|
+
if not managed_external_resources(namespace_info.model_dump(by_alias=True)):
|
|
301
301
|
continue
|
|
302
302
|
|
|
303
303
|
if not account_names:
|
|
304
304
|
tf_namespaces.append(namespace_info)
|
|
305
305
|
continue
|
|
306
306
|
|
|
307
|
-
specs = get_external_resource_specs(namespace_info.
|
|
307
|
+
specs = get_external_resource_specs(namespace_info.model_dump(by_alias=True))
|
|
308
308
|
if not specs:
|
|
309
309
|
tf_namespaces.append(namespace_info)
|
|
310
310
|
continue
|
|
@@ -567,7 +567,7 @@ def early_exit_desired_state(*args: Any, **kwargs: Any) -> dict[str, Any]:
|
|
|
567
567
|
}
|
|
568
568
|
for ns_info in get_tf_namespaces():
|
|
569
569
|
for spec in get_external_resource_specs(
|
|
570
|
-
ns_info.
|
|
570
|
+
ns_info.model_dump(by_alias=True), provision_provider=PROVIDER_AWS
|
|
571
571
|
):
|
|
572
572
|
resource_paths = [
|
|
573
573
|
spec.resource.get("defaults"),
|
|
@@ -69,7 +69,7 @@ class ValidationError(Exception):
|
|
|
69
69
|
class TGWAccountProviderInfo(BaseModel):
|
|
70
70
|
name: str
|
|
71
71
|
uid: str
|
|
72
|
-
assume_role: str | None
|
|
72
|
+
assume_role: str | None = None
|
|
73
73
|
assume_region: str
|
|
74
74
|
|
|
75
75
|
|
|
@@ -81,10 +81,10 @@ class Requester(BaseModel):
|
|
|
81
81
|
tgw_id: str
|
|
82
82
|
tgw_arn: str
|
|
83
83
|
region: str
|
|
84
|
-
routes: list[dict] | None
|
|
85
|
-
rules: list[dict] | None
|
|
86
|
-
hostedzones: list[str] | None
|
|
87
|
-
cidr_block: str | None
|
|
84
|
+
routes: list[dict] | None = None
|
|
85
|
+
rules: list[dict] | None = None
|
|
86
|
+
hostedzones: list[str] | None = None
|
|
87
|
+
cidr_block: str | None = None
|
|
88
88
|
cidr_blocks: list[str]
|
|
89
89
|
account: TGWAccountProviderInfo
|
|
90
90
|
|
|
@@ -92,11 +92,11 @@ class Requester(BaseModel):
|
|
|
92
92
|
class Accepter(BaseModel):
|
|
93
93
|
cidr_block: str
|
|
94
94
|
region: str
|
|
95
|
-
vpc_id: str | None
|
|
96
|
-
route_table_ids: list[str] | None
|
|
97
|
-
subnets_id_az: list[dict[str, str]] | None
|
|
95
|
+
vpc_id: str | None = None
|
|
96
|
+
route_table_ids: list[str] | None = None
|
|
97
|
+
subnets_id_az: list[dict[str, str]] | None = None
|
|
98
98
|
account: ClusterAccountProviderInfo
|
|
99
|
-
api_security_group_id: str | None
|
|
99
|
+
api_security_group_id: str | None = None
|
|
100
100
|
|
|
101
101
|
|
|
102
102
|
class DesiredStateItem(BaseModel):
|
|
@@ -193,7 +193,7 @@ def _build_desired_state_tgw_connection(
|
|
|
193
193
|
yield None
|
|
194
194
|
|
|
195
195
|
account_tgws = awsapi.get_tgws_details(
|
|
196
|
-
peer_connection.account.
|
|
196
|
+
peer_connection.account.model_dump(by_alias=True),
|
|
197
197
|
cluster_region,
|
|
198
198
|
cluster_cidr_block,
|
|
199
199
|
tags=peer_connection.tags or {},
|
|
@@ -275,7 +275,7 @@ def _build_accepter(
|
|
|
275
275
|
)
|
|
276
276
|
(vpc_id, route_table_ids, subnets_id_az, api_security_group_id) = (
|
|
277
277
|
awsapi.get_cluster_vpc_details(
|
|
278
|
-
account.
|
|
278
|
+
account.model_dump(by_alias=True),
|
|
279
279
|
route_tables=bool(peer_connection.manage_routes),
|
|
280
280
|
subnets=True,
|
|
281
281
|
hcp_vpc_endpoint_sg=allow_hcp_private_api_access,
|
|
@@ -318,12 +318,12 @@ def _build_ocm_map(
|
|
|
318
318
|
clusters: Iterable[ClusterV1],
|
|
319
319
|
vault_settings: AppInterfaceSettingsV1,
|
|
320
320
|
) -> OCMMap | None:
|
|
321
|
-
ocm_clusters = [c.
|
|
321
|
+
ocm_clusters = [c.model_dump(by_alias=True) for c in clusters if c.ocm]
|
|
322
322
|
return (
|
|
323
323
|
OCMMap(
|
|
324
324
|
clusters=ocm_clusters,
|
|
325
325
|
integration=QONTRACT_INTEGRATION,
|
|
326
|
-
settings=vault_settings.
|
|
326
|
+
settings=vault_settings.model_dump(by_alias=True),
|
|
327
327
|
)
|
|
328
328
|
if ocm_clusters
|
|
329
329
|
# this is a case for an OCP cluster which is not provisioned
|
|
@@ -347,7 +347,7 @@ def _populate_tgw_attachments_working_dirs(
|
|
|
347
347
|
accounts_by_infra_account_name: dict[str, list[dict[str, Any]]] = {}
|
|
348
348
|
for item in desired_state:
|
|
349
349
|
accounts_by_infra_account_name.setdefault(item.infra_acount_name, []).append(
|
|
350
|
-
item.accepter.account.
|
|
350
|
+
item.accepter.account.model_dump(by_alias=True)
|
|
351
351
|
)
|
|
352
352
|
for infra_account_name, accounts in accounts_by_infra_account_name.items():
|
|
353
353
|
ts.populate_additional_providers(infra_account_name, accounts)
|
|
@@ -429,7 +429,9 @@ def setup(
|
|
|
429
429
|
print_to_file: str | None = None,
|
|
430
430
|
) -> tuple[SecretReaderBase, AWSApi, Terraform, Terrascript]:
|
|
431
431
|
tgw_clusters = desired_state_data_source.clusters
|
|
432
|
-
all_accounts = [
|
|
432
|
+
all_accounts = [
|
|
433
|
+
a.model_dump(by_alias=True) for a in desired_state_data_source.accounts
|
|
434
|
+
]
|
|
433
435
|
account_by_name = {a["name"]: a for a in all_accounts}
|
|
434
436
|
vault_settings = get_app_interface_vault_settings()
|
|
435
437
|
secret_reader = create_secret_reader(vault_settings.vault)
|
|
@@ -455,7 +457,7 @@ def setup(
|
|
|
455
457
|
"",
|
|
456
458
|
thread_pool_size,
|
|
457
459
|
tgw_accounts,
|
|
458
|
-
settings=vault_settings.
|
|
460
|
+
settings=vault_settings.model_dump(by_alias=True),
|
|
459
461
|
default_tags=default_tags,
|
|
460
462
|
)
|
|
461
463
|
tgw_rosa_cluster_accounts = [
|
|
@@ -516,7 +518,7 @@ def run(
|
|
|
516
518
|
) -> None:
|
|
517
519
|
desired_state_data_source = _fetch_desired_state_data_source(account_name)
|
|
518
520
|
tgw_accounts = [
|
|
519
|
-
a.
|
|
521
|
+
a.model_dump(by_alias=True)
|
|
520
522
|
for a in _filter_tgw_accounts(
|
|
521
523
|
desired_state_data_source.accounts, desired_state_data_source.clusters
|
|
522
524
|
)
|
|
@@ -573,7 +575,7 @@ def early_exit_desired_state(*args: Any, **kwargs: Any) -> dict[str, Any]:
|
|
|
573
575
|
desired_state = _fetch_desired_state_data_source()
|
|
574
576
|
for a in desired_state.accounts:
|
|
575
577
|
a.deletion_approvals = []
|
|
576
|
-
return desired_state.
|
|
578
|
+
return desired_state.model_dump(by_alias=True)
|
|
577
579
|
|
|
578
580
|
|
|
579
581
|
def desired_state_shard_config() -> DesiredStateShardConfig:
|
|
@@ -162,7 +162,9 @@ class TerraformVpcResources(QontractReconcileIntegration[TerraformVpcResourcesPa
|
|
|
162
162
|
logging.debug("No VPC requests found, nothing to do.")
|
|
163
163
|
sys.exit(ExitCodes.SUCCESS)
|
|
164
164
|
|
|
165
|
-
accounts_untyped: list[dict] = [
|
|
165
|
+
accounts_untyped: list[dict] = [
|
|
166
|
+
acc.model_dump(by_alias=True) for acc in accounts
|
|
167
|
+
]
|
|
166
168
|
try:
|
|
167
169
|
default_tags = get_settings().default_tags
|
|
168
170
|
except ValueError:
|
|
@@ -13,7 +13,7 @@ class CostNamespace(BaseModel, frozen=True):
|
|
|
13
13
|
labels: CostNamespaceLabels
|
|
14
14
|
app_name: str
|
|
15
15
|
cluster_name: str
|
|
16
|
-
cluster_external_id: str | None
|
|
16
|
+
cluster_external_id: str | None = None
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
def get_cost_namespaces(
|
|
@@ -32,7 +32,7 @@ def get_cost_namespaces(
|
|
|
32
32
|
return [
|
|
33
33
|
CostNamespace(
|
|
34
34
|
name=namespace.name,
|
|
35
|
-
labels=CostNamespaceLabels.
|
|
35
|
+
labels=CostNamespaceLabels.model_validate(namespace.labels or {}),
|
|
36
36
|
app_name=namespace.app.name,
|
|
37
37
|
cluster_name=namespace.cluster.name,
|
|
38
38
|
cluster_external_id=namespace.cluster.spec.external_id
|
|
@@ -6,7 +6,6 @@ from typing import Any
|
|
|
6
6
|
from jsonpath_ng.exceptions import JsonPathParserError
|
|
7
7
|
from pydantic import (
|
|
8
8
|
BaseModel,
|
|
9
|
-
Extra,
|
|
10
9
|
Field,
|
|
11
10
|
Json,
|
|
12
11
|
)
|
|
@@ -51,7 +50,12 @@ from reconcile.utils.json import json_dumps
|
|
|
51
50
|
from reconcile.utils.jsonpath import parse_jsonpath
|
|
52
51
|
|
|
53
52
|
|
|
54
|
-
class SaasResourceTemplateTarget(
|
|
53
|
+
class SaasResourceTemplateTarget(
|
|
54
|
+
ConfiguredBaseModel,
|
|
55
|
+
validate_by_alias=True,
|
|
56
|
+
# ignore `namespaceSelector` and 'provider' fields from the GQL schema
|
|
57
|
+
extra="ignore",
|
|
58
|
+
):
|
|
55
59
|
path: str | None = Field(..., alias="path")
|
|
56
60
|
name: str | None = Field(..., alias="name")
|
|
57
61
|
# the namespace must be required to fulfill the saas file schema (utils.saasherder.interface.SaasFile)
|
|
@@ -79,12 +83,8 @@ class SaasResourceTemplateTarget(ConfiguredBaseModel):
|
|
|
79
83
|
digest_size=20,
|
|
80
84
|
).hexdigest()
|
|
81
85
|
|
|
82
|
-
class Config:
|
|
83
|
-
# ignore `namespaceSelector` and 'provider' fields from the GQL schema
|
|
84
|
-
extra = Extra.ignore
|
|
85
|
-
|
|
86
86
|
|
|
87
|
-
class SaasResourceTemplate(ConfiguredBaseModel):
|
|
87
|
+
class SaasResourceTemplate(ConfiguredBaseModel, validate_by_alias=True):
|
|
88
88
|
name: str = Field(..., alias="name")
|
|
89
89
|
url: str = Field(..., alias="url")
|
|
90
90
|
path: str = Field(..., alias="path")
|
|
@@ -97,7 +97,7 @@ class SaasResourceTemplate(ConfiguredBaseModel):
|
|
|
97
97
|
targets: list[SaasResourceTemplateTarget] = Field(..., alias="targets")
|
|
98
98
|
|
|
99
99
|
|
|
100
|
-
class SaasFile(ConfiguredBaseModel):
|
|
100
|
+
class SaasFile(ConfiguredBaseModel, validate_by_alias=True):
|
|
101
101
|
path: str = Field(..., alias="path")
|
|
102
102
|
name: str = Field(..., alias="name")
|
|
103
103
|
labels: Json | None = Field(..., alias="labels")
|
|
@@ -221,7 +221,7 @@ class SaasFileList:
|
|
|
221
221
|
with self._namespaces_as_dict_lock:
|
|
222
222
|
self._namespaces_as_dict_cache = {
|
|
223
223
|
"namespace": [
|
|
224
|
-
ns.
|
|
224
|
+
ns.model_dump(by_alias=True, exclude_none=True)
|
|
225
225
|
for ns in self.namespaces
|
|
226
226
|
]
|
|
227
227
|
}
|
|
@@ -283,7 +283,7 @@ class SaasFileList:
|
|
|
283
283
|
if app_name and saas_file.app.name != app_name:
|
|
284
284
|
continue
|
|
285
285
|
|
|
286
|
-
sf = saas_file.
|
|
286
|
+
sf = saas_file.model_copy(deep=True)
|
|
287
287
|
if env_name:
|
|
288
288
|
for rt in sf.resource_templates[:]:
|
|
289
289
|
for target in rt.targets[:]:
|
|
@@ -314,7 +314,7 @@ def convert_parameters_to_json_string(root: dict[str, Any]) -> dict[str, Any]:
|
|
|
314
314
|
|
|
315
315
|
|
|
316
316
|
def export_model(model: BaseModel) -> dict[str, Any]:
|
|
317
|
-
return convert_parameters_to_json_string(model.
|
|
317
|
+
return convert_parameters_to_json_string(model.model_dump(by_alias=True))
|
|
318
318
|
|
|
319
319
|
|
|
320
320
|
def get_saas_files(
|
|
@@ -32,7 +32,7 @@ def get_selected_app_names(
|
|
|
32
32
|
prefix = f"{namespace.app.parent_app.name}-"
|
|
33
33
|
name = f"{prefix}{namespace.app.name}"
|
|
34
34
|
selected_app_names.add(name)
|
|
35
|
-
app = namespace.app.
|
|
35
|
+
app = namespace.app.model_dump(by_alias=True)
|
|
36
36
|
app["name"] = name
|
|
37
37
|
apps["apps"].append(app)
|
|
38
38
|
|
|
@@ -40,7 +40,7 @@ def get_selected_app_names(
|
|
|
40
40
|
name = f"{namespace.app.name}-{child.name}"
|
|
41
41
|
if name not in selected_app_names:
|
|
42
42
|
selected_app_names.add(f"{namespace.app.name}-{child.name}")
|
|
43
|
-
child_dict = child.
|
|
43
|
+
child_dict = child.model_dump(by_alias=True)
|
|
44
44
|
child_dict["name"] = name
|
|
45
45
|
apps["apps"].append(child_dict)
|
|
46
46
|
|
|
@@ -31,7 +31,7 @@ QONTRACT_INTEGRATION_VERSION = make_semver(1, 0, 0)
|
|
|
31
31
|
|
|
32
32
|
|
|
33
33
|
class UnleashTogglesIntegrationParams(PydanticRunParams):
|
|
34
|
-
instance: str | None
|
|
34
|
+
instance: str | None = None
|
|
35
35
|
|
|
36
36
|
|
|
37
37
|
def feature_toggle_equal(c: FeatureToggle, d: FeatureToggleUnleashV1) -> bool:
|
|
@@ -68,7 +68,9 @@ class UnleashTogglesIntegration(
|
|
|
68
68
|
if not query_func:
|
|
69
69
|
query_func = gql.get_api().query
|
|
70
70
|
return {
|
|
71
|
-
"toggles": [
|
|
71
|
+
"toggles": [
|
|
72
|
+
ft.model_dump() for ft in self.get_unleash_instances(query_func)
|
|
73
|
+
],
|
|
72
74
|
}
|
|
73
75
|
|
|
74
76
|
def get_unleash_instances(
|
reconcile/utils/acs/base.py
CHANGED
|
@@ -6,7 +6,7 @@ from typing import (
|
|
|
6
6
|
)
|
|
7
7
|
|
|
8
8
|
import requests
|
|
9
|
-
from pydantic import BaseModel
|
|
9
|
+
from pydantic import BaseModel, ConfigDict
|
|
10
10
|
|
|
11
11
|
from reconcile.gql_definitions.acs.acs_instances import AcsInstanceV1
|
|
12
12
|
from reconcile.gql_definitions.acs.acs_instances import query as acs_instances_query
|
|
@@ -19,8 +19,11 @@ class AcsBaseApi(BaseModel):
|
|
|
19
19
|
timeout: int = 30
|
|
20
20
|
session: requests.Session = requests.Session()
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
model_config = ConfigDict(
|
|
23
|
+
validate_by_name=True,
|
|
24
|
+
validate_by_alias=True,
|
|
25
|
+
arbitrary_types_allowed=True,
|
|
26
|
+
)
|
|
24
27
|
|
|
25
28
|
def __enter__(self) -> Self:
|
|
26
29
|
return self
|
reconcile/utils/acs/policies.py
CHANGED
|
@@ -11,7 +11,7 @@ class Scope(BaseModel):
|
|
|
11
11
|
"""
|
|
12
12
|
|
|
13
13
|
cluster: str
|
|
14
|
-
namespace: str | None
|
|
14
|
+
namespace: str | None = None
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
class PolicyCondition(BaseModel):
|
|
@@ -23,7 +23,7 @@ class PolicyCondition(BaseModel):
|
|
|
23
23
|
"""
|
|
24
24
|
|
|
25
25
|
field_name: str
|
|
26
|
-
negate: bool | None
|
|
26
|
+
negate: bool | None = None
|
|
27
27
|
values: list[str]
|
|
28
28
|
|
|
29
29
|
|
reconcile/utils/aws_api.py
CHANGED
|
@@ -3,7 +3,6 @@ from __future__ import annotations
|
|
|
3
3
|
import logging
|
|
4
4
|
import operator
|
|
5
5
|
import os
|
|
6
|
-
import re
|
|
7
6
|
from functools import lru_cache
|
|
8
7
|
from threading import Lock
|
|
9
8
|
from typing import (
|
|
@@ -25,6 +24,7 @@ import reconcile.utils.lean_terraform_client as terraform
|
|
|
25
24
|
from reconcile.utils.secret_reader import SecretReader, SecretReaderBase
|
|
26
25
|
|
|
27
26
|
if TYPE_CHECKING:
|
|
27
|
+
import re
|
|
28
28
|
from collections.abc import (
|
|
29
29
|
Iterable,
|
|
30
30
|
Iterator,
|
|
@@ -1074,28 +1074,40 @@ class AWSApi:
|
|
|
1074
1074
|
return [rt["RouteTableId"] for rt in vpc_route_tables]
|
|
1075
1075
|
|
|
1076
1076
|
@staticmethod
|
|
1077
|
-
def
|
|
1078
|
-
|
|
1079
|
-
) -> list[dict[str, Any]]:
|
|
1080
|
-
results = []
|
|
1081
|
-
pattern = re.compile(regex)
|
|
1082
|
-
for i in images:
|
|
1083
|
-
if not re.search(pattern, i["Name"]):
|
|
1084
|
-
continue
|
|
1085
|
-
if i["State"] != "available":
|
|
1086
|
-
continue
|
|
1087
|
-
item = {"image_id": i["ImageId"], "tags": i.get("Tags", [])}
|
|
1088
|
-
results.append(item)
|
|
1077
|
+
def normalize_tags(tags: Iterable[TagTypeDef]) -> dict[str, str]:
|
|
1078
|
+
return {tag["Key"]: tag["Value"] for tag in tags}
|
|
1089
1079
|
|
|
1090
|
-
|
|
1080
|
+
@staticmethod
|
|
1081
|
+
def _filter_amis(
|
|
1082
|
+
images: Iterable[ImageTypeDef],
|
|
1083
|
+
regex: re.Pattern,
|
|
1084
|
+
) -> dict[str, dict[str, str]]:
|
|
1085
|
+
return {
|
|
1086
|
+
image["ImageId"]: AWSApi.normalize_tags(image.get("Tags", []))
|
|
1087
|
+
for image in images
|
|
1088
|
+
if regex.search(image["Name"]) and image["State"] == "available"
|
|
1089
|
+
}
|
|
1091
1090
|
|
|
1092
1091
|
def get_amis_details(
|
|
1093
1092
|
self,
|
|
1094
1093
|
account: Mapping[str, Any],
|
|
1095
1094
|
owner_account: Mapping[str, Any],
|
|
1096
|
-
regex:
|
|
1095
|
+
regex: re.Pattern,
|
|
1097
1096
|
region: str | None = None,
|
|
1098
|
-
) ->
|
|
1097
|
+
) -> dict[str, dict[str, str]]:
|
|
1098
|
+
"""
|
|
1099
|
+
Get AMI details for an account, find AMI name matches regex and state is available.
|
|
1100
|
+
Return ImageId and normalized tags.
|
|
1101
|
+
|
|
1102
|
+
Args:
|
|
1103
|
+
account: AWS account
|
|
1104
|
+
owner_account: AMI owner AWS account uid
|
|
1105
|
+
regex: regex to filter AMI name
|
|
1106
|
+
region: AWS account region
|
|
1107
|
+
|
|
1108
|
+
Returns:
|
|
1109
|
+
dict[str, dict[str, str]]: Key is AMI ImageId, value is AMI normalized tags.
|
|
1110
|
+
"""
|
|
1099
1111
|
ec2 = self._account_ec2_client(account["name"], region_name=region)
|
|
1100
1112
|
images = self.get_account_amis(ec2, owner=owner_account["uid"])
|
|
1101
1113
|
return self._filter_amis(images, regex)
|
|
@@ -1175,12 +1187,31 @@ class AWSApi:
|
|
|
1175
1187
|
client = self._account_cloudwatch_client(account_name, region_name=region_name)
|
|
1176
1188
|
client.delete_log_group(logGroupName=group_name)
|
|
1177
1189
|
|
|
1178
|
-
def
|
|
1179
|
-
self,
|
|
1190
|
+
def create_tags(
|
|
1191
|
+
self,
|
|
1192
|
+
account: Mapping[str, Any],
|
|
1193
|
+
resource_id: str,
|
|
1194
|
+
tags: Mapping[str, str],
|
|
1180
1195
|
) -> None:
|
|
1196
|
+
"""
|
|
1197
|
+
Create tags on EC2 resources (AMI)
|
|
1198
|
+
|
|
1199
|
+
Args:
|
|
1200
|
+
account: AWS account
|
|
1201
|
+
resource_id: AWS resource id
|
|
1202
|
+
tags: tags to update
|
|
1203
|
+
|
|
1204
|
+
Returns:
|
|
1205
|
+
None
|
|
1206
|
+
"""
|
|
1181
1207
|
ec2 = self._account_ec2_client(account["name"])
|
|
1182
|
-
|
|
1183
|
-
|
|
1208
|
+
formatted_tags: list[TagTypeDef] = [
|
|
1209
|
+
{"Key": k, "Value": v} for k, v in tags.items()
|
|
1210
|
+
]
|
|
1211
|
+
ec2.create_tags(
|
|
1212
|
+
Resources=[resource_id],
|
|
1213
|
+
Tags=formatted_tags,
|
|
1214
|
+
)
|
|
1184
1215
|
|
|
1185
1216
|
def get_alb_network_interface_ips(
|
|
1186
1217
|
self, account: awsh.Account, service_name: str
|
|
@@ -52,9 +52,11 @@ class AwsOrganizationOU(BaseModel):
|
|
|
52
52
|
class AWSAccountStatus(BaseModel):
|
|
53
53
|
id: str = Field(..., alias="Id")
|
|
54
54
|
name: str = Field(..., alias="AccountName")
|
|
55
|
-
uid: str | None = Field(alias="AccountId")
|
|
55
|
+
uid: str | None = Field(None, alias="AccountId")
|
|
56
56
|
state: str = Field(..., alias="State")
|
|
57
|
-
failure_reason: CreateAccountFailureReasonType | None = Field(
|
|
57
|
+
failure_reason: CreateAccountFailureReasonType | None = Field(
|
|
58
|
+
None, alias="FailureReason"
|
|
59
|
+
)
|
|
58
60
|
|
|
59
61
|
|
|
60
62
|
class AWSAccount(BaseModel):
|
|
@@ -26,7 +26,7 @@ class Snitch(BaseModel):
|
|
|
26
26
|
interval: str
|
|
27
27
|
alert_type: str
|
|
28
28
|
alert_email: list[str]
|
|
29
|
-
vault_data: str | None
|
|
29
|
+
vault_data: str | None = None
|
|
30
30
|
|
|
31
31
|
def needs_vault_update(self) -> bool:
|
|
32
32
|
return self.vault_data is not None and self.check_in_url != self.vault_data
|
|
@@ -5,7 +5,7 @@ from functools import cached_property
|
|
|
5
5
|
from typing import Any, Self
|
|
6
6
|
|
|
7
7
|
from deepdiff import DeepHash
|
|
8
|
-
from pydantic import BaseModel
|
|
8
|
+
from pydantic import BaseModel, ConfigDict
|
|
9
9
|
|
|
10
10
|
from reconcile.utils.datetime_util import utc_now
|
|
11
11
|
from reconcile.utils.secret_reader import SecretReaderBase
|
|
@@ -17,7 +17,7 @@ CACHE_SOURCE_DIGEST_METADATA_KEY = "cache-source-digest"
|
|
|
17
17
|
LATEST_CACHE_SOURCE_DIGEST_METADATA_KEY = "latest-cache-source-digest"
|
|
18
18
|
|
|
19
19
|
|
|
20
|
-
class CacheKeyWithDigest(BaseModel):
|
|
20
|
+
class CacheKeyWithDigest(BaseModel, frozen=True):
|
|
21
21
|
integration: str
|
|
22
22
|
integration_version: str
|
|
23
23
|
dry_run: bool
|
|
@@ -70,9 +70,6 @@ class CacheKeyWithDigest(BaseModel):
|
|
|
70
70
|
args.append(f"--shard {self.shard}")
|
|
71
71
|
return " ".join(args)
|
|
72
72
|
|
|
73
|
-
class Config:
|
|
74
|
-
frozen = True
|
|
75
|
-
|
|
76
73
|
|
|
77
74
|
class CacheKey(BaseModel):
|
|
78
75
|
integration: str
|
|
@@ -122,9 +119,10 @@ class CacheKey(BaseModel):
|
|
|
122
119
|
"""
|
|
123
120
|
return self.cache_key_with_digest.build_cli_delete_args()
|
|
124
121
|
|
|
125
|
-
|
|
126
|
-
frozen
|
|
127
|
-
|
|
122
|
+
model_config = ConfigDict(
|
|
123
|
+
frozen=True,
|
|
124
|
+
ignored_types=(cached_property,),
|
|
125
|
+
)
|
|
128
126
|
|
|
129
127
|
|
|
130
128
|
class CacheValue(BaseModel):
|
|
@@ -168,7 +166,7 @@ class EarlyExitCache:
|
|
|
168
166
|
|
|
169
167
|
def get(self, key: CacheKey) -> CacheValue:
|
|
170
168
|
value = self.state.get(str(key))
|
|
171
|
-
return CacheValue.
|
|
169
|
+
return CacheValue.model_validate(value)
|
|
172
170
|
|
|
173
171
|
def set(
|
|
174
172
|
self,
|
|
@@ -194,7 +192,7 @@ class EarlyExitCache:
|
|
|
194
192
|
}
|
|
195
193
|
self.state.add(
|
|
196
194
|
str(key),
|
|
197
|
-
value.
|
|
195
|
+
value.model_dump(),
|
|
198
196
|
metadata=metadata,
|
|
199
197
|
force=True,
|
|
200
198
|
)
|
reconcile/utils/gitlab_api.py
CHANGED
|
@@ -263,13 +263,13 @@ class GitLabApi:
|
|
|
263
263
|
# we can determine if a pending MR exists based on the title
|
|
264
264
|
return any(mr.title == title for mr in mrs)
|
|
265
265
|
|
|
266
|
-
@retry()
|
|
266
|
+
@retry(no_retry_exceptions=(RuntimeError,))
|
|
267
267
|
def get_project_maintainers(
|
|
268
268
|
self, repo_url: str | None = None, query: dict | None = None
|
|
269
|
-
) -> list[str]
|
|
269
|
+
) -> list[str]:
|
|
270
270
|
project = self.project if repo_url is None else self.get_project(repo_url)
|
|
271
271
|
if project is None:
|
|
272
|
-
|
|
272
|
+
raise RuntimeError("project not found")
|
|
273
273
|
members = project.members_all.list(iterator=True, query_parameters=query or {})
|
|
274
274
|
return [m.username for m in members if m.access_level >= 40]
|
|
275
275
|
|
|
@@ -826,14 +826,16 @@ class GitLabApi:
|
|
|
826
826
|
)
|
|
827
827
|
|
|
828
828
|
def get_commit_sha(self, ref: str, repo_url: str) -> str:
|
|
829
|
-
project
|
|
829
|
+
if not (project := self.get_project(repo_url)):
|
|
830
|
+
raise ValueError(f"Project not found for repo_url: {repo_url}")
|
|
830
831
|
commits = project.commits.list(ref_name=ref, per_page=1, page=1)
|
|
831
832
|
return commits[0].id
|
|
832
833
|
|
|
833
834
|
def repository_compare(
|
|
834
835
|
self, repo_url: str, ref_from: str, ref_to: str
|
|
835
836
|
) -> list[dict[str, Any]]:
|
|
836
|
-
project
|
|
837
|
+
if not (project := self.get_project(repo_url)):
|
|
838
|
+
raise ValueError(f"Project not found for repo_url: {repo_url}")
|
|
837
839
|
response: Any = project.repository_compare(ref_from, ref_to)
|
|
838
840
|
return response.get("commits", [])
|
|
839
841
|
|