refactor(vars): enforce nested system and hypervisor schema
This commit is contained in:
@@ -2,8 +2,10 @@
|
||||
- name: Validate core variables
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- install_type is defined
|
||||
- install_type in ["virtual", "physical"]
|
||||
- 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
|
||||
@@ -17,11 +19,211 @@
|
||||
fail_msg: Invalid core variables were specified, please check your inventory/vars.
|
||||
quiet: true
|
||||
|
||||
- name: Validate install_type/hypervisor relationship
|
||||
- name: Validate hypervisor relationship
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- install_type == "physical" or hypervisor_type in ["libvirt", "proxmox", "vmware", "xen"]
|
||||
fail_msg: "hypervisor must be one of: libvirt, proxmox, vmware, xen when install_type=virtual."
|
||||
- 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:
|
||||
- type
|
||||
- url
|
||||
- username
|
||||
- password
|
||||
- host
|
||||
- storage
|
||||
- datacenter
|
||||
- cluster
|
||||
- validate_certs
|
||||
- ssh
|
||||
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:
|
||||
- type
|
||||
- os
|
||||
- os_version
|
||||
- name
|
||||
- id
|
||||
- cpus
|
||||
- memory
|
||||
- balloon
|
||||
- network
|
||||
- vlan
|
||||
- ip
|
||||
- prefix
|
||||
- gateway
|
||||
- dns
|
||||
- path
|
||||
- packages
|
||||
- disks
|
||||
- user
|
||||
- root
|
||||
- luks
|
||||
- features
|
||||
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 nested system schema
|
||||
vars:
|
||||
dns_allowed_keys: [servers, search]
|
||||
user_allowed_keys: [name, password, public_key]
|
||||
root_allowed_keys: [password]
|
||||
luks_allowed_keys:
|
||||
- enabled
|
||||
- passphrase
|
||||
- mapper_name
|
||||
- auto_decrypt
|
||||
- auto_decrypt_method
|
||||
- tpm2_device
|
||||
- tpm2_pcrs
|
||||
- keyfile_size
|
||||
- options
|
||||
- type
|
||||
- cipher
|
||||
- hash
|
||||
- iter_time
|
||||
- key_size
|
||||
- pbkdf
|
||||
- use_urandom
|
||||
- verify_passphrase
|
||||
features_allowed_keys:
|
||||
- cis
|
||||
- selinux
|
||||
- firewall
|
||||
- ssh
|
||||
- zstd
|
||||
- swap
|
||||
- banner
|
||||
- chroot
|
||||
feature_leaf_allowed:
|
||||
cis: [enabled]
|
||||
selinux: [enabled]
|
||||
firewall: [enabled, backend, toolkit]
|
||||
ssh: [enabled]
|
||||
zstd: [enabled]
|
||||
swap: [enabled]
|
||||
banner: [motd, sudo]
|
||||
chroot: [tool]
|
||||
dns_keys: "{{ (system.dns | default({})) | dict2items | map(attribute='key') | list }}"
|
||||
user_keys: "{{ (system.user | default({})) | dict2items | map(attribute='key') | list }}"
|
||||
root_keys: "{{ (system.root | default({})) | dict2items | map(attribute='key') | list }}"
|
||||
luks_keys: "{{ (system.luks | default({})) | dict2items | map(attribute='key') | list }}"
|
||||
features_keys: "{{ (system.features | default({})) | dict2items | map(attribute='key') | list }}"
|
||||
dns_unknown: "{{ dns_keys | difference(dns_allowed_keys) }}"
|
||||
user_unknown: "{{ user_keys | difference(user_allowed_keys) }}"
|
||||
root_unknown: "{{ root_keys | difference(root_allowed_keys) }}"
|
||||
luks_unknown: "{{ luks_keys | difference(luks_allowed_keys) }}"
|
||||
features_unknown: "{{ features_keys | difference(features_allowed_keys) }}"
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- system.dns is not defined or system.dns is mapping
|
||||
- system.user is not defined or system.user is mapping
|
||||
- system.root is not defined or system.root is mapping
|
||||
- system.luks is not defined or system.luks is mapping
|
||||
- system.features is not defined or system.features is mapping
|
||||
- dns_unknown | length == 0
|
||||
- user_unknown | length == 0
|
||||
- root_unknown | length == 0
|
||||
- luks_unknown | length == 0
|
||||
- features_unknown | length == 0
|
||||
fail_msg: >-
|
||||
Invalid nested system schema.
|
||||
dns_unknown={{ dns_unknown | join(',') }},
|
||||
user_unknown={{ user_unknown | join(',') }},
|
||||
root_unknown={{ root_unknown | join(',') }},
|
||||
luks_unknown={{ luks_unknown | join(',') }},
|
||||
features_unknown={{ features_unknown | join(',') }}
|
||||
quiet: true
|
||||
|
||||
- name: Validate feature leaf schemas
|
||||
vars:
|
||||
system_features: "{{ system.features | default({}) }}"
|
||||
feature_keys: "{{ system_features | dict2items | map(attribute='key') | list }}"
|
||||
feature_leaf_allowed:
|
||||
cis: [enabled]
|
||||
selinux: [enabled]
|
||||
firewall: [enabled, backend, toolkit]
|
||||
ssh: [enabled]
|
||||
zstd: [enabled]
|
||||
swap: [enabled]
|
||||
banner: [motd, sudo]
|
||||
chroot: [tool]
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- >-
|
||||
(
|
||||
feature_keys
|
||||
| map('extract', system_features)
|
||||
| select('mapping')
|
||||
| list
|
||||
| length
|
||||
)
|
||||
== (feature_keys | length)
|
||||
- >-
|
||||
(
|
||||
(
|
||||
system_features.cis | default({})
|
||||
) | dict2items | map(attribute='key') | list | difference(feature_leaf_allowed.cis)
|
||||
) | length == 0
|
||||
- >-
|
||||
(
|
||||
(
|
||||
system_features.selinux | default({})
|
||||
) | dict2items | map(attribute='key') | list | difference(feature_leaf_allowed.selinux)
|
||||
) | length == 0
|
||||
- >-
|
||||
(
|
||||
(
|
||||
system_features.firewall | default({})
|
||||
) | dict2items | map(attribute='key') | list | difference(feature_leaf_allowed.firewall)
|
||||
) | length == 0
|
||||
- >-
|
||||
(
|
||||
(
|
||||
system_features.ssh | default({})
|
||||
) | dict2items | map(attribute='key') | list | difference(feature_leaf_allowed.ssh)
|
||||
) | length == 0
|
||||
- >-
|
||||
(
|
||||
(
|
||||
system_features.zstd | default({})
|
||||
) | dict2items | map(attribute='key') | list | difference(feature_leaf_allowed.zstd)
|
||||
) | length == 0
|
||||
- >-
|
||||
(
|
||||
(
|
||||
system_features.swap | default({})
|
||||
) | dict2items | map(attribute='key') | list | difference(feature_leaf_allowed.swap)
|
||||
) | length == 0
|
||||
- >-
|
||||
(
|
||||
(
|
||||
system_features.banner | default({})
|
||||
) | dict2items | map(attribute='key') | list | difference(feature_leaf_allowed.banner)
|
||||
) | length == 0
|
||||
- >-
|
||||
(
|
||||
(
|
||||
system_features.chroot | default({})
|
||||
) | dict2items | map(attribute='key') | list | difference(feature_leaf_allowed.chroot)
|
||||
) | length == 0
|
||||
fail_msg: "Invalid system.features schema detected."
|
||||
quiet: true
|
||||
|
||||
- name: Validate OS and version inputs
|
||||
@@ -59,23 +261,23 @@
|
||||
|
||||
- name: Validate Proxmox hypervisor inputs
|
||||
when:
|
||||
- install_type == "virtual"
|
||||
- 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.node | string | length > 0
|
||||
- hypervisor_cfg.host | string | length > 0
|
||||
- hypervisor_cfg.storage | string | length > 0
|
||||
- system_cfg.id | string | length > 0
|
||||
- system_cfg.network | string | length > 0
|
||||
fail_msg: "Missing required Proxmox inputs. Define hypervisor.(url,username,password,node,storage) and system.(id,network)."
|
||||
fail_msg: "Missing required Proxmox inputs. Define hypervisor.(url,username,password,host,storage) and system.(id,network)."
|
||||
quiet: true
|
||||
|
||||
- name: Validate VMware hypervisor inputs
|
||||
when:
|
||||
- install_type == "virtual"
|
||||
- system_cfg.type == "virtual"
|
||||
- hypervisor_type == "vmware"
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
@@ -91,7 +293,7 @@
|
||||
|
||||
- name: Validate Xen hypervisor inputs
|
||||
when:
|
||||
- install_type == "virtual"
|
||||
- system_cfg.type == "virtual"
|
||||
- hypervisor_type == "xen"
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
@@ -102,40 +304,32 @@
|
||||
- name: Validate virtual installer ISO requirement
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- install_type == "physical" or (boot_iso is defined and (boot_iso | string | length) > 0)
|
||||
fail_msg: "boot_iso is required when install_type=virtual."
|
||||
- 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:
|
||||
- firewall_backend is defined
|
||||
- firewall_backend in ["firewalld", "ufw"]
|
||||
- firewall_toolkit is defined
|
||||
- firewall_toolkit in ["iptables", "nftables"]
|
||||
- firewall_enabled is defined
|
||||
- motd_enabled is defined
|
||||
- sudo_banner_enabled is defined
|
||||
- luks_enabled is defined
|
||||
- chroot_tool is defined
|
||||
- chroot_tool in ["arch-chroot", "chroot", "systemd-nspawn"]
|
||||
- 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 system configuration exists
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- system_cfg is defined
|
||||
- system_cfg is mapping
|
||||
fail_msg: "system configuration is missing. Define system: {...}."
|
||||
quiet: true
|
||||
|
||||
- name: Validate virtual system sizing
|
||||
when: install_type == "virtual"
|
||||
when: system_cfg.type == "virtual"
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- system_cfg.cpus is defined and (system_cfg.cpus | int) > 0
|
||||
- system_cfg.memory_mb is defined and (system_cfg.memory_mb | 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
|
||||
@@ -145,25 +339,25 @@
|
||||
(system_cfg.disks[0].size | float)
|
||||
>= (
|
||||
(
|
||||
(system_cfg.memory_mb | float / 1024 >= 16.0)
|
||||
(system_cfg.memory | float / 1024 >= 16.0)
|
||||
| ternary(
|
||||
(system_cfg.memory_mb | float / 2048),
|
||||
[system_cfg.memory_mb | float / 1024, 4.0] | max
|
||||
(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_mb, and system.disks[0].size."
|
||||
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: install_type == "virtual"
|
||||
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 install_type=virtual: {{ item | to_json }}"
|
||||
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:
|
||||
@@ -175,8 +369,8 @@
|
||||
- system_cfg.disks | length > 0
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- (system_cfg.disks[0].mount | default('') | string | trim) == ''
|
||||
fail_msg: "system.disks[0].mount must be empty; use system.disks[1:] for additional mounts."
|
||||
- (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
|
||||
@@ -185,6 +379,7 @@
|
||||
{{
|
||||
(system_cfg.disks | default([]))
|
||||
| map(attribute='mount')
|
||||
| map(attribute='path')
|
||||
| map('string')
|
||||
| map('trim')
|
||||
| reject('equalto', '')
|
||||
@@ -208,8 +403,8 @@
|
||||
- /var/cache/pacman/pkg
|
||||
- /var/log
|
||||
- /var/log/audit
|
||||
disk_mount: "{{ (item.mount | default('') | string) | trim }}"
|
||||
disk_fstype: "{{ (item.fstype | default('') | string) | trim }}"
|
||||
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:
|
||||
@@ -218,8 +413,8 @@
|
||||
- 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 install_type == "virtual" or (disk_device | length) > 0
|
||||
- disk_mount == "" or install_type != "virtual" or (disk_size | float) > 0
|
||||
- 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 }}"
|
||||
|
||||
Reference in New Issue
Block a user