From b8c672507ffa0208a930d59c6a71a667952a341d Mon Sep 17 00:00:00 2001 From: Sandwich Date: Wed, 11 Feb 2026 05:37:18 +0100 Subject: [PATCH] refactor(vars): simplify normalization and remove effective intermediates --- main.yml | 40 +- roles/configuration/tasks/encryption.yml | 12 +- .../tasks/encryption/keyfile.yml | 4 +- roles/configuration/tasks/encryption/tpm2.yml | 10 +- roles/configuration/tasks/network.yml | 10 +- roles/global_defaults/tasks/hypervisor.yml | 10 +- roles/global_defaults/tasks/system.yml | 549 +++++++----------- roles/partitioning/defaults/main.yml | 10 +- roles/partitioning/tasks/main.yml | 31 +- 9 files changed, 267 insertions(+), 409 deletions(-) diff --git a/main.yml b/main.yml index 56400f3..6c4a8fb 100644 --- a/main.yml +++ b/main.yml @@ -30,30 +30,6 @@ system_input: "{{ system | default({}) }}" system_user_input: "{{ (system_input.user | default({})) if (system_input.user is mapping) else {} }}" system_root_input: "{{ (system_input.root | default({})) if (system_input.root is mapping) else {} }}" - system_user_name_effective: >- - {{ - (system_user_input.name | default('') | string) - if (system_user_input.name | default('') | string | length) > 0 - else (system_user_name | default('') | string) - }} - system_user_public_key_effective: >- - {{ - (system_user_input.public_key | default('') | string) - if (system_user_input.public_key | default('') | string | length) > 0 - else (system_user_public_key | default('') | string) - }} - system_user_password_effective: >- - {{ - (system_user_input.password | default('') | string) - if (system_user_input.password | default('') | string | length) > 0 - else (system_user_password | default('') | string) - }} - system_root_password_effective: >- - {{ - (system_root_input.password | default('') | string) - if (system_root_input.password | default('') | string | length) > 0 - else (system_root_password | default('') | string) - }} ansible.builtin.set_fact: system: >- {{ @@ -61,12 +37,20 @@ | combine( { 'user': { - 'name': system_user_name_effective, - 'public_key': system_user_public_key_effective, - 'password': system_user_password_effective + 'name': ( + (system_user_input.name | default('') | string | length) > 0 + ) | ternary(system_user_input.name | string, system_user_name | default('') | string), + 'public_key': ( + (system_user_input.public_key | default('') | string | length) > 0 + ) | ternary(system_user_input.public_key | string, system_user_public_key | default('') | string), + 'password': ( + (system_user_input.password | default('') | string | length) > 0 + ) | ternary(system_user_input.password | string, system_user_password | default('') | string) }, 'root': { - 'password': system_root_password_effective + 'password': ( + (system_root_input.password | default('') | string | length) > 0 + ) | ternary(system_root_input.password | string, system_root_password | default('') | string) } }, recursive=True diff --git a/roles/configuration/tasks/encryption.yml b/roles/configuration/tasks/encryption.yml index 499031a..1c0c937 100644 --- a/roles/configuration/tasks/encryption.yml +++ b/roles/configuration/tasks/encryption.yml @@ -2,7 +2,7 @@ - name: Configure disk encryption when: partitioning_luks_enabled | bool vars: - configuration_luks_passphrase_effective: >- + configuration_luks_passphrase: >- {{ partitioning_luks_passphrase | string }} block: - name: Set LUKS configuration facts @@ -12,7 +12,7 @@ configuration_luks_device_value: "{{ partitioning_luks_device }}" configuration_luks_tpm2_pcrs_raw: >- {{ partitioning_luks_tpm2_pcrs }} - configuration_luks_tpm2_pcrs_effective_value: >- + configuration_luks_tpm2_pcrs_normalized: >- {{ ( configuration_luks_tpm2_pcrs_raw @@ -41,7 +41,7 @@ configuration_luks_tpm2_device: >- {{ partitioning_luks_tpm2_device }} configuration_luks_tpm2_pcrs: "{{ configuration_luks_tpm2_pcrs_raw }}" - configuration_luks_tpm2_pcrs_effective: "{{ configuration_luks_tpm2_pcrs_effective_value }}" + configuration_luks_tpm2_pcrs_normalized: "{{ configuration_luks_tpm2_pcrs_normalized }}" configuration_luks_keyfile_path: >- /etc/cryptsetup-keys.d/{{ configuration_luks_mapper_name_value }}.key changed_when: false @@ -56,7 +56,7 @@ when: configuration_luks_auto_method in ['tpm2', 'keyfile'] ansible.builtin.assert: that: - - configuration_luks_passphrase_effective | length > 0 + - configuration_luks_passphrase | length > 0 fail_msg: system.luks.passphrase must be set for LUKS auto-decrypt. no_log: true @@ -82,8 +82,8 @@ (configuration_luks_auto_method == 'tpm2') | ternary( ['tpm2-device=' + configuration_luks_tpm2_device] - + (['tpm2-pcrs=' + configuration_luks_tpm2_pcrs_effective] - if configuration_luks_tpm2_pcrs_effective | length > 0 else []), + + (['tpm2-pcrs=' + configuration_luks_tpm2_pcrs_normalized] + if configuration_luks_tpm2_pcrs_normalized | length > 0 else []), [] ) }} diff --git a/roles/configuration/tasks/encryption/keyfile.yml b/roles/configuration/tasks/encryption/keyfile.yml index 05b6f5f..d0b4290 100644 --- a/roles/configuration/tasks/encryption/keyfile.yml +++ b/roles/configuration/tasks/encryption/keyfile.yml @@ -52,7 +52,7 @@ when: configuration_luks_keyfile_unlock_test.rc != 0 community.crypto.luks_device: device: "{{ configuration_luks_device }}" - passphrase: "{{ configuration_luks_passphrase_effective }}" + passphrase: "{{ configuration_luks_passphrase }}" new_keyfile: "/mnt{{ configuration_luks_keyfile_path }}" register: configuration_luks_addkey_result failed_when: false @@ -84,7 +84,7 @@ - name: Retry adding keyfile to LUKS header community.crypto.luks_device: device: "{{ configuration_luks_device }}" - passphrase: "{{ configuration_luks_passphrase_effective }}" + passphrase: "{{ configuration_luks_passphrase }}" new_keyfile: "/mnt{{ configuration_luks_keyfile_path }}" register: configuration_luks_addkey_retry failed_when: false diff --git a/roles/configuration/tasks/encryption/tpm2.yml b/roles/configuration/tasks/encryption/tpm2.yml index a31aa13..95c14a9 100644 --- a/roles/configuration/tasks/encryption/tpm2.yml +++ b/roles/configuration/tasks/encryption/tpm2.yml @@ -11,7 +11,7 @@ - name: Write passphrase into temporary file for TPM2 enrollment ansible.builtin.copy: dest: "{{ configuration_luks_tpm2_passphrase_tempfile.path }}" - content: "{{ configuration_luks_passphrase_effective }}" + content: "{{ configuration_luks_passphrase }}" owner: root group: root mode: "0600" @@ -31,8 +31,8 @@ | regex_replace('^/mnt', '') ) ] - + (['--tpm2-pcrs=' + configuration_luks_tpm2_pcrs_effective] - if configuration_luks_tpm2_pcrs_effective | length > 0 else []) + + (['--tpm2-pcrs=' + configuration_luks_tpm2_pcrs_normalized] + if configuration_luks_tpm2_pcrs_normalized | length > 0 else []) + [configuration_luks_device] }} configuration_luks_enroll_chroot_cmd: >- @@ -55,8 +55,8 @@ '--wipe-slot=tpm2', '--unlock-key-file=' + configuration_luks_tpm2_passphrase_tempfile.path ] - + (['--tpm2-pcrs=' + configuration_luks_tpm2_pcrs_effective] - if configuration_luks_tpm2_pcrs_effective | length > 0 else []) + + (['--tpm2-pcrs=' + configuration_luks_tpm2_pcrs_normalized] + if configuration_luks_tpm2_pcrs_normalized | length > 0 else []) + [configuration_luks_device] }} ansible.builtin.command: diff --git a/roles/configuration/tasks/network.yml b/roles/configuration/tasks/network.yml index 944d18e..4eaf62e 100644 --- a/roles/configuration/tasks/network.yml +++ b/roles/configuration/tasks/network.yml @@ -30,17 +30,17 @@ ) | default('') }} - configuration_net_inf_effective: >- + configuration_net_inf_detected: >- {{ configuration_net_inf_from_facts | default(configuration_net_inf_from_ip, true) }} - configuration_net_inf_regex: "{{ configuration_net_inf_effective | ansible.builtin.regex_escape }}" + configuration_net_inf_regex: "{{ configuration_net_inf_detected | ansible.builtin.regex_escape }}" configuration_net_mac_from_virtualization: "{{ virtualization_mac_address | default('') }}" configuration_net_mac_from_facts: >- {{ ( - (ansible_facts | default({})).get(configuration_net_inf_effective, {}).get('macaddress', '') + (ansible_facts | default({})).get(configuration_net_inf_detected, {}).get('macaddress', '') ) | default( - (ansible_facts | default({})).get('ansible_' + configuration_net_inf_effective, {}).get('macaddress', ''), + (ansible_facts | default({})).get('ansible_' + configuration_net_inf_detected, {}).get('macaddress', ''), true ) }} @@ -58,7 +58,7 @@ | default('') }} ansible.builtin.set_fact: - configuration_net_inf: "{{ configuration_net_inf_effective }}" + configuration_net_inf: "{{ configuration_net_inf_detected }}" configuration_net_mac: >- {{ ( diff --git a/roles/global_defaults/tasks/hypervisor.yml b/roles/global_defaults/tasks/hypervisor.yml index eed0ad4..25ab0f7 100644 --- a/roles/global_defaults/tasks/hypervisor.yml +++ b/roles/global_defaults/tasks/hypervisor.yml @@ -15,12 +15,8 @@ - name: Normalize hypervisor configuration vars: - hypervisor_cfg_effective: >- - {{ - hypervisor_defaults - | combine(hypervisor, recursive=True) - }} + hypervisor_cfg_normalized: "{{ hypervisor_defaults | combine(hypervisor, recursive=True) }}" ansible.builtin.set_fact: - hypervisor_cfg: "{{ hypervisor_cfg_effective }}" - hypervisor_type: "{{ hypervisor_cfg_effective.type | string | lower }}" + hypervisor_cfg: "{{ hypervisor_cfg_normalized }}" + hypervisor_type: "{{ hypervisor_cfg_normalized.type | string | lower }}" changed_when: false diff --git a/roles/global_defaults/tasks/system.yml b/roles/global_defaults/tasks/system.yml index 75a45ad..42aff2a 100644 --- a/roles/global_defaults/tasks/system.yml +++ b/roles/global_defaults/tasks/system.yml @@ -11,296 +11,196 @@ fail_msg: "system must be a dictionary" quiet: true -- name: Normalize base system fields +- name: Reject deprecated top-level system selectors + ansible.builtin.assert: + that: + - os is not defined + - os_version is not defined + - hostname is not defined + fail_msg: >- + Top-level `os`, `os_version`, and `hostname` are not supported. + Define these values under `system` (`system.os`, `system.os_version`, `system.name`). + quiet: true + +- name: Build normalized system configuration vars: - system_type_effective: >- + system_raw: "{{ system_defaults | combine(system, recursive=True) }}" + system_type: "{{ system_raw.type | string | lower }}" + system_os_input: "{{ system_raw.os | default('') | string | lower }}" + system_name: >- {{ - system.type - if system.type is defined and (system.type | string | length) > 0 - else system_defaults.type - }} - system_name_effective: >- - {{ - system.name - if system.name is defined and (system.name | string | length) > 0 + system_raw.name | string + if (system_raw.name | default('') | string | length) > 0 else inventory_hostname }} - system_os_effective: >- + + system_dns_raw: "{{ system_raw.dns if system_raw.dns is mapping else {} }}" + system_dns_servers_input: "{{ system_dns_raw.servers | default([]) }}" + system_dns_search_input: "{{ system_dns_raw.search | default([]) }}" + + system_user_raw: "{{ system_raw.user if system_raw.user is mapping else {} }}" + system_root_raw: "{{ system_raw.root if system_raw.root is mapping else {} }}" + system_luks_raw: "{{ system_raw.luks if system_raw.luks is mapping else {} }}" + system_features_raw: "{{ system_raw.features if system_raw.features is mapping else {} }}" + + system_feature_cis_raw: >- {{ - system.os - if system.os is defined and (system.os | string | length) > 0 - else ('archlinux' if (system_type_effective | lower) == 'physical' else '') + system_features_raw.cis + if system_features_raw.cis is defined and system_features_raw.cis is mapping + else {} }} - system_os_version_effective: >- + system_feature_selinux_raw: >- {{ - system.os_version - if system.os_version is defined and (system.os_version | string | length) > 0 - else '' + system_features_raw.selinux + if system_features_raw.selinux is defined and system_features_raw.selinux is mapping + else {} }} - system_id_effective: >- + system_feature_firewall_raw: >- {{ - system.id - if system.id is defined and (system.id | string | length) > 0 - else '' + system_features_raw.firewall + if system_features_raw.firewall is defined and system_features_raw.firewall is mapping + else {} }} - system_cpus_effective: >- + system_feature_ssh_raw: >- {{ - system.cpus - if system.cpus is defined and (system.cpus | int) > 0 - else 0 + system_features_raw.ssh + if system_features_raw.ssh is defined and system_features_raw.ssh is mapping + else {} }} - system_memory_effective: >- + system_feature_zstd_raw: >- {{ - system.memory - if system.memory is defined and (system.memory | int) > 0 - else 0 + system_features_raw.zstd + if system_features_raw.zstd is defined and system_features_raw.zstd is mapping + else {} }} - system_balloon_effective: >- + system_feature_swap_raw: >- {{ - system.balloon - if system.balloon is defined and (system.balloon | int) > 0 - else 0 + system_features_raw.swap + if system_features_raw.swap is defined and system_features_raw.swap is mapping + else {} }} - system_network_effective: >- + system_feature_banner_raw: >- {{ - system.network - if system.network is defined and (system.network | string | length) > 0 - else '' + system_features_raw.banner + if system_features_raw.banner is defined and system_features_raw.banner is mapping + else {} }} - system_vlan_effective: >- + system_feature_chroot_raw: >- {{ - system.vlan - if system.vlan is defined and (system.vlan | string | length) > 0 - else '' - }} - system_ip_effective: >- - {{ - system.ip - if system.ip is defined and (system.ip | string | length) > 0 - else '' - }} - system_prefix_effective: >- - {{ - system.prefix - if system.prefix is defined and (system.prefix | int) > 0 - else '' - }} - system_gateway_effective: >- - {{ - system.gateway - if system.gateway is defined and (system.gateway | string | length) > 0 - else '' - }} - system_dns_effective: >- - {{ - (system_defaults.dns | default({'servers': [], 'search': []})) - | combine((system.dns if system.dns is defined else {}), recursive=True) - }} - system_dns_resolvers_value: "{{ system_dns_effective.servers if system_dns_effective.servers is defined else [] }}" - system_dns_resolvers_list_raw: >- - {{ - system_dns_resolvers_value - if system_dns_resolvers_value is iterable and system_dns_resolvers_value is not string - else (system_dns_resolvers_value | string).split(',') - }} - system_dns_resolvers_effective: >- - {{ - system_dns_resolvers_list_raw - | map('trim') - | reject('equalto', '') - | list - }} - system_dns_domains_value: "{{ system_dns_effective.search if system_dns_effective.search is defined else [] }}" - system_dns_domains_list_raw: >- - {{ - system_dns_domains_value - if system_dns_domains_value is iterable and system_dns_domains_value is not string - else (system_dns_domains_value | string).split(',') - }} - system_dns_domains_effective: >- - {{ - system_dns_domains_list_raw - | map('trim') - | reject('equalto', '') - | list - }} - system_path_effective: >- - {{ - system.path - if system.path is defined and (system.path | string | length) > 0 - else '' - }} - system_user_effective: >- - {{ - (system_defaults.user | default({})) - | combine( - (system.user if (system.user is defined and system.user is mapping) else {}), - recursive=True - ) - }} - system_root_effective: >- - {{ - (system_defaults.root | default({})) - | combine( - (system.root if (system.root is defined and system.root is mapping) else {}), - recursive=True - ) - }} - system_luks_effective: >- - {{ - (system_defaults.luks | default({})) - | combine( - (system.luks if (system.luks is defined and system.luks is mapping) else {}), - recursive=True - ) - }} - system_features_effective: >- - {{ - (system_defaults.features | default({})) - | combine( - (system.features if (system.features is defined and system.features is mapping) else {}), - recursive=True - ) - }} - system_user_name_effective: "{{ (system_user_effective.name | default('') | string) }}" - system_user_password_effective: "{{ (system_user_effective.password | default('') | string) }}" - system_user_public_key_effective: "{{ (system_user_effective.public_key | default('') | string) }}" - system_root_password_effective: "{{ (system_root_effective.password | default('') | string) }}" - system_luks_passphrase_effective: "{{ (system_luks_effective.passphrase | default('') | string) }}" - system_luks_mapper_name_effective: "{{ (system_luks_effective.mapper_name | default('SYSTEM_DECRYPTED') | string) }}" - system_luks_auto_decrypt_method_effective: "{{ (system_luks_effective.auto_decrypt_method | default('tpm2') | string | lower) }}" - system_luks_tpm2_device_effective: "{{ (system_luks_effective.tpm2_device | default('auto') | string) }}" - system_luks_tpm2_pcrs_effective: "{{ (system_luks_effective.tpm2_pcrs | default('') | string) }}" - system_luks_options_effective: "{{ (system_luks_effective.options | default('discard,tries=3') | string) }}" - system_luks_type_effective: "{{ (system_luks_effective.type | default('luks2') | string) }}" - system_luks_cipher_effective: "{{ (system_luks_effective.cipher | default('aes-xts-plain64') | string) }}" - system_luks_hash_effective: "{{ (system_luks_effective.hash | default('sha512') | string) }}" - system_luks_iter_time_effective: "{{ (system_luks_effective.iter_time | default(4000) | int) }}" - system_luks_key_size_effective: "{{ (system_luks_effective.key_size | default(512) | int) }}" - system_luks_pbkdf_effective: "{{ (system_luks_effective.pbkdf | default('argon2id') | string) }}" - system_luks_keyfile_size_effective: "{{ (system_luks_effective.keyfile_size | default(64) | int) }}" - system_luks_enabled_effective: "{{ system_luks_effective.enabled | default(false) | bool }}" - system_luks_auto_decrypt_effective: "{{ system_luks_effective.auto_decrypt | default(true) | bool }}" - system_luks_use_urandom_effective: "{{ system_luks_effective.use_urandom | default(true) | bool }}" - system_luks_verify_passphrase_effective: "{{ system_luks_effective.verify_passphrase | default(true) | bool }}" - system_features_cis_enabled_effective: "{{ system_features_effective.cis.enabled | default(false) | bool }}" - system_features_selinux_enabled_effective: "{{ system_features_effective.selinux.enabled | default(true) | bool }}" - system_features_firewall_enabled_effective: "{{ system_features_effective.firewall.enabled | default(true) | bool }}" - system_features_firewall_backend_effective: "{{ (system_features_effective.firewall.backend | default('firewalld') | string | lower) }}" - system_features_firewall_toolkit_effective: "{{ (system_features_effective.firewall.toolkit | default('nftables') | string | lower) }}" - system_features_ssh_enabled_effective: "{{ system_features_effective.ssh.enabled | default(true) | bool }}" - system_features_zstd_enabled_effective: "{{ system_features_effective.zstd.enabled | default(true) | bool }}" - system_features_swap_enabled_effective: "{{ system_features_effective.swap.enabled | default(true) | bool }}" - system_features_banner_motd_effective: "{{ system_features_effective.banner.motd | default(true) | bool }}" - system_features_banner_sudo_effective: "{{ system_features_effective.banner.sudo | default(true) | bool }}" - system_features_chroot_tool_effective: "{{ (system_features_effective.chroot.tool | default('arch-chroot') | string) }}" - system_packages_value: "{{ system.packages if system.packages is defined else [] }}" - system_packages_list_raw: >- - {{ - system_packages_value - if system_packages_value is iterable and system_packages_value is not string - else (system_packages_value | string).split(',') - }} - system_packages_effective: >- - {{ - system_packages_list_raw - | map('trim') - | reject('equalto', '') - | list + system_features_raw.chroot + if system_features_raw.chroot is defined and system_features_raw.chroot is mapping + else {} }} + + system_packages_input: "{{ system_raw.packages | default([]) }}" ansible.builtin.set_fact: - hostname: "{{ system_name_effective }}" - os: "{{ system_os_effective | lower }}" - os_version: "{{ system_os_version_effective | string }}" - system_cfg: >- - {{ - system_defaults - | combine(system, recursive=True) - | combine( - { - 'type': system_type_effective | lower, - 'name': system_name_effective, - 'os': system_os_effective | lower, - 'os_version': system_os_version_effective | string, - 'id': system_id_effective, - 'cpus': system_cpus_effective, - 'memory': system_memory_effective, - 'balloon': system_balloon_effective, - 'network': system_network_effective, - 'vlan': system_vlan_effective, - 'ip': system_ip_effective, - 'prefix': system_prefix_effective, - 'gateway': system_gateway_effective, - 'dns': { - 'servers': system_dns_resolvers_effective, - 'search': system_dns_domains_effective - }, - 'path': system_path_effective, - 'packages': system_packages_effective, - 'user': { - 'name': system_user_name_effective, - 'password': system_user_password_effective, - 'public_key': system_user_public_key_effective - }, - 'root': { - 'password': system_root_password_effective - }, - 'luks': { - 'enabled': system_luks_enabled_effective, - 'passphrase': system_luks_passphrase_effective, - 'mapper_name': system_luks_mapper_name_effective, - 'auto_decrypt': system_luks_auto_decrypt_effective, - 'auto_decrypt_method': system_luks_auto_decrypt_method_effective, - 'tpm2_device': system_luks_tpm2_device_effective, - 'tpm2_pcrs': system_luks_tpm2_pcrs_effective, - 'keyfile_size': system_luks_keyfile_size_effective, - 'options': system_luks_options_effective, - 'type': system_luks_type_effective, - 'cipher': system_luks_cipher_effective, - 'hash': system_luks_hash_effective, - 'iter_time': system_luks_iter_time_effective, - 'key_size': system_luks_key_size_effective, - 'pbkdf': system_luks_pbkdf_effective, - 'use_urandom': system_luks_use_urandom_effective, - 'verify_passphrase': system_luks_verify_passphrase_effective - }, - 'features': { - 'cis': { - 'enabled': system_features_cis_enabled_effective - }, - 'selinux': { - 'enabled': system_features_selinux_enabled_effective - }, - 'firewall': { - 'enabled': system_features_firewall_enabled_effective, - 'backend': system_features_firewall_backend_effective, - 'toolkit': system_features_firewall_toolkit_effective - }, - 'ssh': { - 'enabled': system_features_ssh_enabled_effective - }, - 'zstd': { - 'enabled': system_features_zstd_enabled_effective - }, - 'swap': { - 'enabled': system_features_swap_enabled_effective - }, - 'banner': { - 'motd': system_features_banner_motd_effective, - 'sudo': system_features_banner_sudo_effective - }, - 'chroot': { - 'tool': system_features_chroot_tool_effective - } - } - }, - recursive=True + system_cfg: + type: "{{ system_type }}" + os: "{{ system_os_input if system_os_input | length > 0 else ('archlinux' if system_type == 'physical' else '') }}" + os_version: "{{ system_raw.os_version | default('') | string }}" + name: "{{ system_name }}" + id: "{{ system_raw.id | default('') | string }}" + cpus: "{{ [system_raw.cpus | default(0) | int, 0] | max }}" + memory: "{{ [system_raw.memory | default(0) | int, 0] | max }}" + balloon: "{{ [system_raw.balloon | default(0) | int, 0] | max }}" + network: "{{ system_raw.network | default('') | string }}" + vlan: "{{ system_raw.vlan | default('') | string }}" + ip: "{{ system_raw.ip | default('') | string }}" + prefix: >- + {{ + (system_raw.prefix | int) + if (system_raw.prefix | default('') | string | length) > 0 + else '' + }} + gateway: "{{ system_raw.gateway | default('') | string }}" + dns: + servers: >- + {{ + ( + system_dns_servers_input + if system_dns_servers_input is iterable and system_dns_servers_input is not string + else (system_dns_servers_input | string).split(',') + ) + | map('trim') + | reject('equalto', '') + | list + }} + search: >- + {{ + ( + system_dns_search_input + if system_dns_search_input is iterable and system_dns_search_input is not string + else (system_dns_search_input | string).split(',') + ) + | map('trim') + | reject('equalto', '') + | list + }} + path: "{{ system_raw.path | default('') | string }}" + packages: >- + {{ + ( + system_packages_input + if system_packages_input is iterable and system_packages_input is not string + else (system_packages_input | string).split(',') ) - }} + | map('trim') + | reject('equalto', '') + | list + }} + disks: "{{ system_raw.disks | default([]) }}" + user: + name: "{{ system_user_raw.name | default('') | string }}" + password: "{{ system_user_raw.password | default('') | string }}" + public_key: "{{ system_user_raw.public_key | default('') | string }}" + root: + password: "{{ system_root_raw.password | default('') | string }}" + luks: + enabled: "{{ system_luks_raw.enabled | default(system_defaults.luks.enabled) | bool }}" + passphrase: "{{ system_luks_raw.passphrase | default(system_defaults.luks.passphrase) | string }}" + mapper_name: "{{ system_luks_raw.mapper_name | default(system_defaults.luks.mapper_name) | string }}" + auto_decrypt: "{{ system_luks_raw.auto_decrypt | default(system_defaults.luks.auto_decrypt) | bool }}" + auto_decrypt_method: "{{ system_luks_raw.auto_decrypt_method | default(system_defaults.luks.auto_decrypt_method) | string | lower }}" + tpm2_device: "{{ system_luks_raw.tpm2_device | default(system_defaults.luks.tpm2_device) | string }}" + tpm2_pcrs: "{{ system_luks_raw.tpm2_pcrs | default(system_defaults.luks.tpm2_pcrs) | string }}" + keyfile_size: "{{ system_luks_raw.keyfile_size | default(system_defaults.luks.keyfile_size) | int }}" + options: "{{ system_luks_raw.options | default(system_defaults.luks.options) | string }}" + type: "{{ system_luks_raw.type | default(system_defaults.luks.type) | string }}" + cipher: "{{ system_luks_raw.cipher | default(system_defaults.luks.cipher) | string }}" + hash: "{{ system_luks_raw.hash | default(system_defaults.luks.hash) | string }}" + iter_time: "{{ system_luks_raw.iter_time | default(system_defaults.luks.iter_time) | int }}" + key_size: "{{ system_luks_raw.key_size | default(system_defaults.luks.key_size) | int }}" + pbkdf: "{{ system_luks_raw.pbkdf | default(system_defaults.luks.pbkdf) | string }}" + use_urandom: "{{ system_luks_raw.use_urandom | default(system_defaults.luks.use_urandom) | bool }}" + verify_passphrase: "{{ system_luks_raw.verify_passphrase | default(system_defaults.luks.verify_passphrase) | bool }}" + features: + cis: + enabled: "{{ system_feature_cis_raw.enabled | default(system_defaults.features.cis.enabled) | bool }}" + selinux: + enabled: "{{ system_feature_selinux_raw.enabled | default(system_defaults.features.selinux.enabled) | bool }}" + firewall: + enabled: "{{ system_feature_firewall_raw.enabled | default(system_defaults.features.firewall.enabled) | bool }}" + backend: "{{ system_feature_firewall_raw.backend | default(system_defaults.features.firewall.backend) | string | lower }}" + toolkit: "{{ system_feature_firewall_raw.toolkit | default(system_defaults.features.firewall.toolkit) | string | lower }}" + ssh: + enabled: "{{ system_feature_ssh_raw.enabled | default(system_defaults.features.ssh.enabled) | bool }}" + zstd: + enabled: "{{ system_feature_zstd_raw.enabled | default(system_defaults.features.zstd.enabled) | bool }}" + swap: + enabled: "{{ system_feature_swap_raw.enabled | default(system_defaults.features.swap.enabled) | bool }}" + banner: + motd: "{{ system_feature_banner_raw.motd | default(system_defaults.features.banner.motd) | bool }}" + sudo: "{{ system_feature_banner_raw.sudo | default(system_defaults.features.banner.sudo) | bool }}" + chroot: + tool: "{{ system_feature_chroot_raw.tool | default(system_defaults.features.chroot.tool) | string }}" + hostname: "{{ system_name }}" + os: "{{ system_os_input if system_os_input | length > 0 else ('archlinux' if system_type == 'physical' else '') }}" + os_version: "{{ system_raw.os_version | default('') | string }}" changed_when: false - name: Normalize system disks input vars: + system_disks: "{{ system_cfg.disks | default([]) }}" system_disk_defaults: size: 0 device: "" @@ -309,37 +209,26 @@ fstype: "" label: "" opts: "defaults" - system_disks_raw: >- - {{ - system_cfg.disks - if system_cfg.disks is defined - else [] - }} - system_disks_effective: >- - {{ - system_disks_raw - }} + system_disk_letter_map: "abcdefghijklmnopqrstuvwxyz" system_disk_device_prefix: >- {{ '/dev/vd' - if (system_cfg.type | lower) == 'virtual' and (hypervisor_type | default('')) == 'libvirt' + if system_cfg.type == 'virtual' and hypervisor_type == 'libvirt' else ( '/dev/xvd' - if (system_cfg.type | lower) == 'virtual' and (hypervisor_type | default('')) == 'xen' + if system_cfg.type == 'virtual' and hypervisor_type == 'xen' else ( '/dev/sd' - if (system_cfg.type | lower) == 'virtual' - and (hypervisor_type | default('')) in ['proxmox', 'vmware'] + if system_cfg.type == 'virtual' and hypervisor_type in ['proxmox', 'vmware'] else '' ) ) }} - system_disk_letter_map: "abcdefghijklmnopqrstuvwxyz" block: - name: Validate system disks type ansible.builtin.assert: that: - - system_disks_effective is sequence + - system_disks is sequence fail_msg: "system.disks must be a list" quiet: true @@ -349,7 +238,7 @@ - item is mapping fail_msg: "Each system disk entry must be a dictionary" quiet: true - loop: "{{ system_disks_effective }}" + loop: "{{ system_disks }}" loop_control: label: "{{ item | to_json }}" @@ -359,14 +248,14 @@ - item.mount is not defined or item.mount is mapping fail_msg: "system.disks[].mount must be a dictionary (e.g. mount: {path: /data})." quiet: true - loop: "{{ system_disks_effective }}" + loop: "{{ system_disks }}" loop_control: label: "{{ item | to_json }}" - name: Validate system disk count ansible.builtin.assert: that: - - (system_disks_effective | length) <= 26 + - (system_disks | length) <= 26 fail_msg: "system.disks supports at most 26 entries." quiet: true @@ -376,63 +265,55 @@ changed_when: false - name: Build normalized system disk configuration - ansible.builtin.set_fact: - system_disks_cfg: "{{ system_disks_cfg | default([]) + [system_disk_cfg] }}" vars: disk_idx: "{{ ansible_loop.index0 }}" disk_letter: "{{ system_disk_letter_map[disk_idx] }}" - disk_device_default: >- + disk_cfg_base: "{{ system_disk_defaults | combine(item, recursive=True) }}" + disk_mount: "{{ system_disk_defaults.mount | combine((disk_cfg_base.mount | default({})), recursive=True) }}" + disk_mount_path: "{{ (disk_mount.path | default('') | string) | trim }}" + disk_mount_fstype: >- {{ - (system_disk_device_prefix ~ disk_letter) - if (system_cfg.type | lower) == 'virtual' + disk_mount.fstype + if (disk_mount.fstype | default('') | string | length) > 0 + else ('ext4' if disk_mount_path | length > 0 else '') + }} + disk_device: >- + {{ + disk_cfg_base.device + if (disk_cfg_base.device | string | length) > 0 + else ( + (system_disk_device_prefix ~ disk_letter) + if system_cfg.type == 'virtual' + else '' + ) + }} + disk_partition: >- + {{ + disk_device ~ ('p1' if (disk_device | regex_search('\\d$')) else '1') + if disk_device | length > 0 else '' }} - system_disk_cfg_base: "{{ system_disk_defaults | combine(item, recursive=True) }}" - system_disk_mount_path: "{{ (system_disk_cfg_base.mount.path | default('') | string) | trim }}" - system_disk_cfg_tmp: >- + ansible.builtin.set_fact: + system_disks_cfg: >- {{ - system_disk_cfg_base - | combine( - { - 'device': ( - system_disk_cfg_base.device - if system_disk_cfg_base.device | string | length > 0 - else disk_device_default - ), - 'mount': ( - system_disk_cfg_base.mount - | combine( - { - 'path': system_disk_mount_path, - 'fstype': ( - system_disk_cfg_base.mount.fstype - if (system_disk_cfg_base.mount.fstype | default('') | string | length) > 0 - else ('ext4' if system_disk_mount_path | length > 0 else '') - ) - }, - recursive=True - ) - ) - }, - recursive=True - ) + system_disks_cfg + [ + disk_cfg_base + | combine( + { + 'device': disk_device, + 'mount': { + 'path': disk_mount_path, + 'fstype': disk_mount_fstype, + 'label': disk_mount.label | default('') | string, + 'opts': disk_mount.opts | default('defaults') | string + }, + 'partition': disk_partition + }, + recursive=True + ) + ] }} - system_disk_partition_device: >- - {{ - system_disk_cfg_tmp.device - ~ ('p1' if (system_disk_cfg_tmp.device | regex_search('\\d$')) else '1') - }} - system_disk_cfg: >- - {{ - system_disk_cfg_tmp - | combine( - { - 'partition': system_disk_partition_device - }, - recursive=True - ) - }} - loop: "{{ system_disks_effective }}" + loop: "{{ system_disks }}" loop_control: loop_var: item extended: true @@ -440,10 +321,10 @@ - name: Update system configuration with normalized disks ansible.builtin.set_fact: - system_cfg: "{{ system_cfg | combine({'disks': system_disks_cfg | default([])}, recursive=True) }}" + system_cfg: "{{ system_cfg | combine({'disks': system_disks_cfg}, recursive=True) }}" changed_when: false - - name: Set install_drive from system disk definition + - name: Set install_drive from primary disk when: - system_disks_cfg | length > 0 - system_disks_cfg[0].device | string | length > 0 diff --git a/roles/partitioning/defaults/main.yml b/roles/partitioning/defaults/main.yml index 7162962..35828ba 100644 --- a/roles/partitioning/defaults/main.yml +++ b/roles/partitioning/defaults/main.yml @@ -114,7 +114,7 @@ partitioning_root_device: >- if (partitioning_luks_enabled | bool) else install_drive ~ (partitioning_root_partition_suffix | string) }} -partitioning_vm_size_effective: >- +partitioning_disk_size_gb: >- {{ ( partitioning_vm_size @@ -129,7 +129,7 @@ partitioning_vm_size_effective: >- ) | float }} -partitioning_vm_memory_effective: >- +partitioning_memory_mb: >- {{ ( partitioning_vm_memory @@ -143,9 +143,9 @@ partitioning_vm_memory_effective: >- }} partitioning_swap_size_gb: >- {{ - ((partitioning_vm_memory_effective / 1024) >= 16.0) + ((partitioning_memory_mb / 1024) >= 16.0) | ternary( - (partitioning_vm_memory_effective / 2048) | int, - [partitioning_vm_memory_effective / 1024, 4.0] | max | int + (partitioning_memory_mb / 2048) | int, + [partitioning_memory_mb / 1024, 4.0] | max | int ) }} diff --git a/roles/partitioning/tasks/main.yml b/roles/partitioning/tasks/main.yml index e8393e7..4a81ba8 100644 --- a/roles/partitioning/tasks/main.yml +++ b/roles/partitioning/tasks/main.yml @@ -155,14 +155,11 @@ - name: Configure LUKS encryption when: partitioning_luks_enabled | bool - vars: - partitioning_luks_passphrase_effective: >- - {{ partitioning_luks_passphrase | string }} block: - name: Validate LUKS passphrase ansible.builtin.assert: that: - - partitioning_luks_passphrase_effective | length > 0 + - (partitioning_luks_passphrase | string | length) > 0 fail_msg: system.luks.passphrase must be set when LUKS is enabled. no_log: true @@ -177,7 +174,7 @@ pbkdf: algorithm: "{{ partitioning_luks_pbkdf }}" iteration_time: "{{ (partitioning_luks_iter_time | float) / 1000 }}" - passphrase: "{{ partitioning_luks_passphrase_effective }}" + passphrase: "{{ partitioning_luks_passphrase | string }}" register: partitioning_luks_format_result no_log: true @@ -206,7 +203,7 @@ device: "{{ partitioning_luks_device }}" state: opened name: "{{ partitioning_luks_mapper_name }}" - passphrase: "{{ partitioning_luks_passphrase_effective }}" + passphrase: "{{ partitioning_luks_passphrase | string }}" allow_discards: "{{ 'discard' in (partitioning_luks_options | lower) }}" register: partitioning_luks_open_result no_log: true @@ -234,7 +231,7 @@ device: "{{ partitioning_luks_device }}" state: opened name: "{{ partitioning_luks_mapper_name }}" - passphrase: "{{ partitioning_luks_passphrase_effective }}" + passphrase: "{{ partitioning_luks_passphrase | string }}" allow_discards: "{{ 'discard' in (partitioning_luks_options | lower) }}" register: partitioning_luks_open_retry no_log: true @@ -275,7 +272,7 @@ {{ ( [ - (partitioning_vm_memory_effective | float / 1024), + (partitioning_memory_mb | float / 1024), 4 ] | max | float ) @@ -287,14 +284,14 @@ ( 4 + [ - (partitioning_vm_size_effective | float) - 20, + (partitioning_disk_size_gb | float) - 20, 0 ] | max ) if system_cfg.features.swap.enabled | bool else 0 }} - partitioning_lvm_swap_target_effective_gb: >- + partitioning_lvm_swap_target_limited_gb: >- {{ ( [ @@ -310,7 +307,7 @@ ( [ ( - (partitioning_vm_size_effective | float) + (partitioning_disk_size_gb | float) - (partitioning_reserved_gb | float) - (system_cfg.features.cis.enabled | ternary(7.5, 0)) - partitioning_lvm_extent_reserve_gb @@ -325,16 +322,16 @@ partitioning_lvm_available_gb: >- {{ ( - (partitioning_vm_size_effective | float) + (partitioning_disk_size_gb | float) - (partitioning_reserved_gb | float) - (system_cfg.features.cis.enabled | ternary(7.5, 0)) - partitioning_lvm_extent_reserve_gb - - partitioning_lvm_swap_target_effective_gb + - partitioning_lvm_swap_target_limited_gb ) | float }} partitioning_lvm_home_gb: >- {{ - ([([(((partitioning_vm_size_effective | float) - 20) * 0.1), 2] | max), 20] | min) + ([([(((partitioning_disk_size_gb | float) - 20) * 0.1), 2] | max), 20] | min) }} partitioning_lvm_root_default_gb: >- {{ @@ -346,7 +343,7 @@ ( ((partitioning_lvm_available_gb | float) > 12) | ternary( - ((partitioning_vm_size_effective | float) * 0.4) + ((partitioning_disk_size_gb | float) * 0.4) | round(0, 'ceil'), partitioning_lvm_available_gb ) @@ -360,7 +357,7 @@ {{ ( [ - partitioning_lvm_swap_target_effective_gb, + partitioning_lvm_swap_target_limited_gb, partitioning_lvm_swap_max_gb ] | min | round(2, 'floor') ) @@ -371,7 +368,7 @@ {{ [ ( - (partitioning_vm_size_effective | float) + (partitioning_disk_size_gb | float) - (partitioning_reserved_gb | float) - (partitioning_lvm_swap_gb | float) - partitioning_lvm_extent_reserve_gb