338 lines
13 KiB
YAML
338 lines
13 KiB
YAML
---
|
|
- name: Validate core variables
|
|
ansible.builtin.assert:
|
|
that:
|
|
- system_cfg is defined
|
|
- system_cfg is mapping
|
|
- system_cfg.type is defined
|
|
- system_cfg.type in ["virtual", "physical"]
|
|
- hypervisor_cfg is defined
|
|
- hypervisor_cfg is mapping
|
|
- hypervisor_type is defined
|
|
- hypervisor_type in ["libvirt", "proxmox", "vmware", "xen", "none"]
|
|
- system_cfg.filesystem is defined
|
|
- system_cfg.filesystem in ["btrfs", "ext4", "xfs"]
|
|
- install_drive is defined
|
|
- install_drive | string | length > 0
|
|
- hostname is defined
|
|
- hostname | string | length > 0
|
|
fail_msg: Invalid core variables were specified, please check your inventory/vars.
|
|
quiet: true
|
|
|
|
- name: Validate hypervisor relationship
|
|
ansible.builtin.assert:
|
|
that:
|
|
- system_cfg.type == "physical" or hypervisor_type in ["libvirt", "proxmox", "vmware", "xen"]
|
|
fail_msg: "hypervisor.type must be one of: libvirt, proxmox, vmware, xen when system.type=virtual."
|
|
quiet: true
|
|
|
|
- name: Validate hypervisor schema
|
|
vars:
|
|
hypervisor_allowed_keys: "{{ hypervisor_defaults | dict2items | map(attribute='key') | list }}"
|
|
hypervisor_keys: "{{ (hypervisor | default({})) | dict2items | map(attribute='key') | list }}"
|
|
hypervisor_unknown_keys: "{{ hypervisor_keys | difference(hypervisor_allowed_keys) }}"
|
|
ansible.builtin.assert:
|
|
that:
|
|
- hypervisor_unknown_keys | length == 0
|
|
fail_msg: "Unsupported hypervisor keys: {{ hypervisor_unknown_keys | join(', ') }}"
|
|
quiet: true
|
|
|
|
- name: Validate system schema
|
|
vars:
|
|
system_allowed_keys: "{{ system_defaults | dict2items | map(attribute='key') | list }}"
|
|
system_keys: "{{ (system | default({})) | dict2items | map(attribute='key') | list }}"
|
|
system_unknown_keys: "{{ system_keys | difference(system_allowed_keys) }}"
|
|
ansible.builtin.assert:
|
|
that:
|
|
- system_unknown_keys | length == 0
|
|
fail_msg: "Unsupported system keys: {{ system_unknown_keys | join(', ') }}."
|
|
quiet: true
|
|
|
|
- name: Validate system sub-dict schemas
|
|
loop:
|
|
- network
|
|
- root
|
|
- luks
|
|
loop_control:
|
|
label: "system.{{ item }}"
|
|
vars:
|
|
sub_input: "{{ (system[item] | default({})) | dict2items | map(attribute='key') | list }}"
|
|
sub_allowed: "{{ system_defaults[item] | dict2items | map(attribute='key') | list }}"
|
|
sub_unknown: "{{ sub_input | difference(sub_allowed) }}"
|
|
ansible.builtin.assert:
|
|
that:
|
|
- sub_unknown | length == 0
|
|
fail_msg: "Unsupported system.{{ item }} keys: {{ sub_unknown | join(', ') }}"
|
|
quiet: true
|
|
|
|
- name: Validate system.luks.tpm2 schema
|
|
vars:
|
|
tpm2_input: >-
|
|
{{
|
|
(system.luks if (system.luks is defined and system.luks is mapping) else {}).tpm2
|
|
| default({})
|
|
}}
|
|
tpm2_allowed_keys: "{{ system_defaults.luks.tpm2 | dict2items | map(attribute='key') | list }}"
|
|
tpm2_unknown: "{{ (tpm2_input | dict2items | map(attribute='key') | list) | difference(tpm2_allowed_keys) }}"
|
|
ansible.builtin.assert:
|
|
that:
|
|
- system.luks is not defined or system.luks.tpm2 is not defined or system.luks.tpm2 is mapping
|
|
- tpm2_unknown | length == 0
|
|
fail_msg: "Unsupported system.luks.tpm2 keys: {{ tpm2_unknown | join(', ') }}"
|
|
quiet: true
|
|
|
|
- name: Validate system.features schema
|
|
vars:
|
|
features_allowed_keys: "{{ system_defaults.features | dict2items | map(attribute='key') | list }}"
|
|
features_unknown: >-
|
|
{{
|
|
((system.features | default({})) | dict2items | map(attribute='key') | list)
|
|
| difference(features_allowed_keys)
|
|
}}
|
|
ansible.builtin.assert:
|
|
that:
|
|
- features_unknown | length == 0
|
|
fail_msg: "Unsupported system.features keys: {{ features_unknown | join(', ') }}"
|
|
quiet: true
|
|
|
|
- name: Validate system.features leaf schemas
|
|
loop: "{{ system_defaults.features | dict2items }}"
|
|
loop_control:
|
|
label: "system.features.{{ item.key }}"
|
|
vars:
|
|
feature_input: "{{ (system.features | default({}))[item.key] | default({}) }}"
|
|
feature_allowed_keys: "{{ item.value | dict2items | map(attribute='key') | list }}"
|
|
feature_unknown: "{{ (feature_input | dict2items | map(attribute='key') | list) | difference(feature_allowed_keys) }}"
|
|
ansible.builtin.assert:
|
|
that:
|
|
- feature_input is mapping
|
|
- feature_unknown | length == 0
|
|
fail_msg: "Unsupported system.features.{{ item.key }} keys: {{ feature_unknown | join(', ') }}"
|
|
quiet: true
|
|
|
|
- name: Validate OS and version inputs
|
|
ansible.builtin.assert:
|
|
that:
|
|
- os is defined
|
|
- os in ["almalinux", "alpine", "archlinux", "debian", "fedora", "opensuse", "rhel", "rocky", "ubuntu", "ubuntu-lts", "void"]
|
|
- >-
|
|
os not in ["debian", "fedora", "rocky", "almalinux", "rhel"]
|
|
or (os_version is defined and (os_version | string | length) > 0)
|
|
- >-
|
|
os_version is not defined or (os_version | string | length) == 0
|
|
or (
|
|
os == "debian" and (os_version | string) in ["10", "11", "12", "13", "unstable"]
|
|
) or (
|
|
os == "fedora" and (os_version | string) in ["40", "41", "42", "43"]
|
|
) or (
|
|
os in ["rocky", "almalinux"]
|
|
and (os_version | string) is match("^(8|9|10)(\\.\\d+)?$")
|
|
) or (
|
|
os == "rhel"
|
|
and (os_version | string) is match("^(8|9|10)(\\.\\d+)?$")
|
|
) or (
|
|
os in ["alpine", "archlinux", "opensuse", "ubuntu", "ubuntu-lts", "void"]
|
|
)
|
|
fail_msg: "Invalid os/version specified. Please check README.md for supported values."
|
|
quiet: true
|
|
|
|
- name: Validate RHEL ISO requirement
|
|
ansible.builtin.assert:
|
|
that:
|
|
- os != "rhel" or (rhel_iso is defined and (rhel_iso | string | length) > 0)
|
|
fail_msg: "rhel_iso is required when os=rhel."
|
|
quiet: true
|
|
|
|
- name: Validate Proxmox hypervisor inputs
|
|
when:
|
|
- system_cfg.type == "virtual"
|
|
- hypervisor_type == "proxmox"
|
|
ansible.builtin.assert:
|
|
that:
|
|
- hypervisor_cfg.url | string | length > 0
|
|
- hypervisor_cfg.username | string | length > 0
|
|
- hypervisor_cfg.password | string | length > 0
|
|
- hypervisor_cfg.host | string | length > 0
|
|
- hypervisor_cfg.storage | string | length > 0
|
|
- system_cfg.id | string | length > 0
|
|
- >-
|
|
(system_cfg.network.bridge | default('') | string | length > 0)
|
|
or (system_cfg.network.interfaces | default([]) | length > 0)
|
|
fail_msg: >-
|
|
Missing required Proxmox inputs. Define hypervisor.(url,username,password,host,storage),
|
|
system.id, and system.network.bridge (or system.network.interfaces[]).
|
|
quiet: true
|
|
|
|
- name: Validate VMware hypervisor inputs
|
|
when:
|
|
- system_cfg.type == "virtual"
|
|
- hypervisor_type == "vmware"
|
|
ansible.builtin.assert:
|
|
that:
|
|
- hypervisor_cfg.url | string | length > 0
|
|
- hypervisor_cfg.username | string | length > 0
|
|
- hypervisor_cfg.password | string | length > 0
|
|
- hypervisor_cfg.datacenter | string | length > 0
|
|
- hypervisor_cfg.cluster | string | length > 0
|
|
- hypervisor_cfg.storage | string | length > 0
|
|
- >-
|
|
(system_cfg.network.bridge | default('') | string | length > 0)
|
|
or (system_cfg.network.interfaces | default([]) | length > 0)
|
|
fail_msg: >-
|
|
Missing required VMware inputs. Define hypervisor.(url,username,password,datacenter,cluster,storage)
|
|
and system.network.bridge (or system.network.interfaces[]).
|
|
quiet: true
|
|
|
|
- name: Validate Xen hypervisor inputs
|
|
when:
|
|
- system_cfg.type == "virtual"
|
|
- hypervisor_type == "xen"
|
|
ansible.builtin.assert:
|
|
that:
|
|
- >-
|
|
(system_cfg.network.bridge | default('') | string | length > 0)
|
|
or (system_cfg.network.interfaces | default([]) | length > 0)
|
|
fail_msg: "Missing required Xen inputs. Define system.network.bridge (or system.network.interfaces[])."
|
|
quiet: true
|
|
|
|
- name: Validate virtual installer ISO requirement
|
|
ansible.builtin.assert:
|
|
that:
|
|
- system_cfg.type == "physical" or (boot_iso is defined and (boot_iso | string | length) > 0)
|
|
fail_msg: "boot_iso is required when system.type=virtual."
|
|
quiet: true
|
|
|
|
- name: Validate firewall and feature flags
|
|
ansible.builtin.assert:
|
|
that:
|
|
- system_cfg.features.firewall.backend is defined
|
|
- system_cfg.features.firewall.backend in ["firewalld", "ufw"]
|
|
- system_cfg.features.firewall.toolkit is defined
|
|
- system_cfg.features.firewall.toolkit in ["iptables", "nftables"]
|
|
- system_cfg.features.firewall.enabled is defined
|
|
- system_cfg.features.banner.motd is defined
|
|
- system_cfg.features.banner.sudo is defined
|
|
- system_cfg.luks.enabled is defined
|
|
- system_cfg.features.chroot.tool is defined
|
|
- system_cfg.features.chroot.tool in ["arch-chroot", "chroot", "systemd-nspawn"]
|
|
fail_msg: Invalid feature flags were specified, please check your inventory/vars.
|
|
quiet: true
|
|
|
|
- name: Validate virtual system sizing
|
|
when: system_cfg.type == "virtual"
|
|
ansible.builtin.assert:
|
|
that:
|
|
- system_cfg.cpus is defined and (system_cfg.cpus | int) > 0
|
|
- system_cfg.memory is defined and (system_cfg.memory | int) > 0
|
|
- system_cfg.disks is defined and (system_cfg.disks | length) > 0
|
|
- (system_cfg.disks[0].size | float) > 0
|
|
- (system_cfg.disks[0].size | float) >= 20
|
|
- >-
|
|
system_cfg.filesystem != "btrfs"
|
|
or (
|
|
(system_cfg.disks[0].size | float)
|
|
>= (
|
|
(
|
|
(system_cfg.memory | float / 1024 >= 16.0)
|
|
| ternary(
|
|
(system_cfg.memory | float / 2048),
|
|
[system_cfg.memory | float / 1024, 4.0] | max
|
|
)
|
|
)
|
|
+ 5.5
|
|
)
|
|
)
|
|
fail_msg: "Invalid system sizing. Check system.cpus, system.memory, and system.disks[0].size."
|
|
quiet: true
|
|
|
|
- name: Validate all virtual disks have a positive size
|
|
when: system_cfg.type == "virtual"
|
|
ansible.builtin.assert:
|
|
that:
|
|
- item.size is defined
|
|
- (item.size | float) > 0
|
|
fail_msg: "Each system disk must have a positive size when system.type=virtual: {{ item | to_json }}"
|
|
quiet: true
|
|
loop: "{{ system_cfg.disks | default([]) }}"
|
|
loop_control:
|
|
label: "{{ item | to_json }}"
|
|
|
|
- name: Validate primary disk mount is not used
|
|
when:
|
|
- system_cfg.disks is defined
|
|
- system_cfg.disks | length > 0
|
|
ansible.builtin.assert:
|
|
that:
|
|
- (system_cfg.disks[0].mount.path | default('') | string | trim) == ''
|
|
fail_msg: "system.disks[0].mount.path must be empty; use system.disks[1:] for additional mounts."
|
|
quiet: true
|
|
|
|
- name: Validate disk mountpoint inputs
|
|
vars:
|
|
system_disk_mounts: >-
|
|
{{
|
|
(system_cfg.disks | default([]))
|
|
| map(attribute='mount')
|
|
| map(attribute='path')
|
|
| map('string')
|
|
| map('trim')
|
|
| reject('equalto', '')
|
|
| list
|
|
}}
|
|
ansible.builtin.assert:
|
|
that:
|
|
- system_disk_mounts | length == (system_disk_mounts | unique | list | length)
|
|
fail_msg: "Duplicate disk mountpoints found in system.disks."
|
|
quiet: true
|
|
|
|
- name: Validate disk mount definitions
|
|
when: system_cfg.disks is defined
|
|
vars:
|
|
reserved_mounts:
|
|
- /boot
|
|
- /boot/efi
|
|
- /home
|
|
- /swap
|
|
- /var
|
|
- /var/cache/pacman/pkg
|
|
- /var/log
|
|
- /var/log/audit
|
|
disk_mount: "{{ (item.mount.path | default('') | string) | trim }}"
|
|
disk_fstype: "{{ (item.mount.fstype | default('') | string) | trim }}"
|
|
disk_device: "{{ (item.device | default('') | string) | trim }}"
|
|
disk_size: "{{ item.size | default(0) }}"
|
|
ansible.builtin.assert:
|
|
that:
|
|
- disk_mount == "" or disk_mount.startswith("/")
|
|
- disk_mount == "" or disk_mount != "/"
|
|
- disk_mount == "" or disk_mount not in reserved_mounts
|
|
- disk_mount == "" or disk_fstype in ["btrfs", "ext4", "xfs"]
|
|
- disk_mount == "" or system_cfg.type == "virtual" or (disk_device | length) > 0
|
|
- disk_mount == "" or system_cfg.type != "virtual" or (disk_size | float) > 0
|
|
fail_msg: "Invalid system disk entry: {{ item | to_json }}"
|
|
quiet: true
|
|
loop: "{{ system_cfg.disks }}"
|
|
loop_control:
|
|
label: "{{ item | to_json }}"
|
|
|
|
- name: Validate static IP requirements
|
|
when: system_cfg.network.ip is defined and (system_cfg.network.ip | string | length) > 0
|
|
ansible.builtin.assert:
|
|
that:
|
|
- system_cfg.network.prefix is defined
|
|
- (system_cfg.network.prefix | int) > 0
|
|
fail_msg: "system.network.prefix is required when system.network.ip is set."
|
|
quiet: true
|
|
|
|
- name: Validate network interfaces entries
|
|
when: system_cfg.network.interfaces | default([]) | length > 0
|
|
ansible.builtin.assert:
|
|
that:
|
|
- item is mapping
|
|
- item.bridge is defined and (item.bridge | string | length) > 0
|
|
fail_msg: "Each system.network.interfaces[] entry must be a dict with at least a 'bridge' key."
|
|
quiet: true
|
|
loop: "{{ system_cfg.network.interfaces }}"
|
|
loop_control:
|
|
label: "{{ item | to_json }}"
|