Files
Ansible-Bootstrap/roles/global_defaults/tasks/system.yml

329 lines
12 KiB
YAML

---
- name: Ensure system input is a dictionary
ansible.builtin.set_fact:
system: "{{ system | default({}) }}"
changed_when: false
- name: Validate system input type
ansible.builtin.assert:
that:
- system is mapping
fail_msg: "system must be a dictionary"
quiet: true
- name: Build normalized system configuration
vars:
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_raw.name | string | trim
if (system_raw.name | default('') | string | trim | length) > 0
else inventory_hostname
}}
system_dns: >-
{{
system_defaults.dns
| combine((system_raw.dns if system_raw.dns is mapping else {}), recursive=True)
}}
system_user: >-
{{
system_defaults.user
| combine((system_raw.user if system_raw.user is mapping else {}), recursive=True)
}}
system_root: >-
{{
system_defaults.root
| combine((system_raw.root if system_raw.root is mapping else {}), recursive=True)
}}
system_luks: >-
{{
system_defaults.luks
| combine((system_raw.luks if system_raw.luks is mapping else {}), recursive=True)
}}
system_luks_tpm2: >-
{{
system_defaults.luks.tpm2
| combine((system_luks.tpm2 if system_luks.tpm2 is mapping else {}), recursive=True)
}}
system_features: >-
{{
system_defaults.features
| combine((system_raw.features if system_raw.features is mapping else {}), recursive=True)
}}
system_feature_cis: >-
{{
system_defaults.features.cis
| combine((system_features.cis if system_features.cis is mapping else {}), recursive=True)
}}
system_feature_selinux: >-
{{
system_defaults.features.selinux
| combine((system_features.selinux if system_features.selinux is mapping else {}), recursive=True)
}}
system_feature_firewall: >-
{{
system_defaults.features.firewall
| combine((system_features.firewall if system_features.firewall is mapping else {}), recursive=True)
}}
system_feature_ssh: >-
{{
system_defaults.features.ssh
| combine((system_features.ssh if system_features.ssh is mapping else {}), recursive=True)
}}
system_feature_zstd: >-
{{
system_defaults.features.zstd
| combine((system_features.zstd if system_features.zstd is mapping else {}), recursive=True)
}}
system_feature_swap: >-
{{
system_defaults.features.swap
| combine((system_features.swap if system_features.swap is mapping else {}), recursive=True)
}}
system_feature_banner: >-
{{
system_defaults.features.banner
| combine((system_features.banner if system_features.banner is mapping else {}), recursive=True)
}}
system_feature_chroot: >-
{{
system_defaults.features.chroot
| combine((system_features.chroot if system_features.chroot is mapping else {}), recursive=True)
}}
system_dns_servers_input: "{{ system_dns.servers | default([]) }}"
system_dns_search_input: "{{ system_dns.search | default([]) }}"
system_packages_input: "{{ system_raw.packages | default([]) }}"
ansible.builtin.set_fact:
system_cfg:
type: "{{ system_type }}"
os: "{{ system_os_input if system_os_input | length > 0 else ('archlinux' if system_type == 'physical' else '') }}"
version: "{{ system_raw.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.name | string }}"
password: "{{ system_user.password | string }}"
key: "{{ system_user.key | string }}"
root:
password: "{{ system_root.password | string }}"
luks:
enabled: "{{ system_luks.enabled | bool }}"
passphrase: "{{ system_luks.passphrase | string }}"
mapper: "{{ system_luks.mapper | string }}"
auto: "{{ system_luks.auto | bool }}"
method: "{{ system_luks.method | string | lower }}"
tpm2:
device: "{{ system_luks_tpm2.device | string }}"
pcrs: "{{ system_luks_tpm2.pcrs | string }}"
keysize: "{{ system_luks.keysize | int }}"
options: "{{ system_luks.options | string }}"
type: "{{ system_luks.type | string }}"
cipher: "{{ system_luks.cipher | string }}"
hash: "{{ system_luks.hash | string }}"
iter: "{{ system_luks.iter | int }}"
bits: "{{ system_luks.bits | int }}"
pbkdf: "{{ system_luks.pbkdf | string }}"
urandom: "{{ system_luks.urandom | bool }}"
verify: "{{ system_luks.verify | bool }}"
features:
cis:
enabled: "{{ system_feature_cis.enabled | bool }}"
selinux:
enabled: "{{ system_feature_selinux.enabled | bool }}"
firewall:
enabled: "{{ system_feature_firewall.enabled | bool }}"
backend: "{{ system_feature_firewall.backend | string | lower }}"
toolkit: "{{ system_feature_firewall.toolkit | string | lower }}"
ssh:
enabled: "{{ system_feature_ssh.enabled | bool }}"
zstd:
enabled: "{{ system_feature_zstd.enabled | bool }}"
swap:
enabled: "{{ system_feature_swap.enabled | bool }}"
banner:
motd: "{{ system_feature_banner.motd | bool }}"
sudo: "{{ system_feature_banner.sudo | bool }}"
chroot:
tool: "{{ system_feature_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.version | default('') | string }}"
changed_when: false
- name: Normalize system disks input
vars:
system_disks: "{{ system_cfg.disks | default([]) }}"
system_disk_letter_map: "abcdefghijklmnopqrstuvwxyz"
system_disk_device_prefix: >-
{{
'/dev/vd'
if system_cfg.type == 'virtual' and hypervisor_type == 'libvirt'
else (
'/dev/xvd'
if system_cfg.type == 'virtual' and hypervisor_type == 'xen'
else (
'/dev/sd'
if system_cfg.type == 'virtual' and hypervisor_type in ['proxmox', 'vmware']
else ''
)
)
}}
block:
- name: Validate system disks type
ansible.builtin.assert:
that:
- system_disks is sequence
fail_msg: "system.disks must be a list"
quiet: true
- name: Validate system disk items
ansible.builtin.assert:
that:
- item is mapping
fail_msg: "Each system disk entry must be a dictionary"
quiet: true
loop: "{{ system_disks }}"
loop_control:
label: "{{ item | to_json }}"
- name: Validate system disk mount schema
ansible.builtin.assert:
that:
- 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 }}"
loop_control:
label: "{{ item | to_json }}"
- name: Validate system disk count
ansible.builtin.assert:
that:
- (system_disks | length) <= 26
fail_msg: "system.disks supports at most 26 entries."
quiet: true
- name: Initialize normalized disk list
ansible.builtin.set_fact:
system_disks_cfg: []
changed_when: false
- name: Build normalized system disk configuration
vars:
disk_idx: "{{ ansible_loop.index0 }}"
disk_letter: "{{ system_disk_letter_map[disk_idx] }}"
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: >-
{{
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 ''
}}
ansible.builtin.set_fact:
system_disks_cfg: >-
{{
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
)
]
}}
loop: "{{ system_disks }}"
loop_control:
loop_var: item
extended: true
label: "{{ item | to_json }}"
- name: Update system configuration with normalized disks
ansible.builtin.set_fact:
system_cfg: "{{ system_cfg | combine({'disks': system_disks_cfg}, recursive=True) }}"
changed_when: false
- name: Set install_drive from primary disk
when:
- system_disks_cfg | length > 0
- system_disks_cfg[0].device | string | length > 0
ansible.builtin.set_fact:
install_drive: "{{ system_disks_cfg[0].device }}"
changed_when: false