feat(network): make interfaces[] canonical, normalize flat fields as AWX compat

This commit is contained in:
2026-02-12 22:17:02 +01:00
parent 5108e46a4c
commit 66057bc9b2
17 changed files with 222 additions and 159 deletions

View File

@@ -36,13 +36,14 @@ system_defaults:
dns:
servers: []
search: []
interfaces: []
path: ""
packages: []
disks: []
user:
name: ""
password: ""
key: []
keys: []
root:
password: ""
luks:

View File

@@ -16,7 +16,7 @@
fail_msg: "system and its nested keys (network, user, root, luks, features) must be dictionaries."
quiet: true
- name: Validate DNS and user.key are lists (not strings)
- name: Validate DNS and user.keys are lists (not strings)
when: system.network is defined and system.network.dns is defined
ansible.builtin.assert:
that:
@@ -25,12 +25,12 @@
fail_msg: "system.network.dns.servers and system.network.dns.search must be lists, not strings."
quiet: true
- name: Validate user.key is a list
when: system.user is defined and system.user.key is defined
- name: Validate user.keys is a list
when: system.user is defined and system.user.keys is defined
ansible.builtin.assert:
that:
- system.user.key is iterable and system.user.key is not string
fail_msg: "system.user.key must be a list of SSH public key strings."
- system.user.keys is iterable and system.user.keys is not string
fail_msg: "system.user.keys must be a list of SSH public key strings."
quiet: true
- name: Validate system features input types
@@ -88,6 +88,27 @@
dns:
servers: "{{ system_raw.network.dns.servers | default([]) }}"
search: "{{ system_raw.network.dns.search | default([]) }}"
interfaces: >-
{{
system_raw.network.interfaces
if (system_raw.network.interfaces | default([]) | length > 0)
else (
[{
'name': 'eth0',
'bridge': system_raw.network.bridge | default('') | string,
'vlan': system_raw.network.vlan | default('') | string,
'ip': system_raw.network.ip | default('') | string,
'prefix': (
(system_raw.network.prefix | int | string)
if (system_raw.network.prefix | default('') | string | length) > 0
else ''
),
'gateway': system_raw.network.gateway | default('') | string
}]
if (system_raw.network.bridge | default('') | string | length > 0)
else []
)
}}
path: "{{ system_raw.path | default('') | string }}"
packages: >-
{{
@@ -104,7 +125,7 @@
user:
name: "{{ system_raw.user.name | string }}"
password: "{{ system_raw.user.password | string }}"
key: "{{ system_raw.user.key | default([]) }}"
keys: "{{ system_raw.user.keys | default([]) }}"
root:
password: "{{ system_raw.root.password | string }}"
luks:
@@ -150,6 +171,25 @@
os: "{{ system_os_input if system_os_input | length > 0 else ('archlinux' if system_type == 'physical' else '') }}"
os_version: "{{ system_raw.version | default('') | string }}"
- name: Populate primary network fields from first interface
when:
- system_cfg.network.interfaces | length > 0
- system_cfg.network.bridge | default('') | string | length == 0
vars:
_primary: "{{ system_cfg.network.interfaces[0] }}"
ansible.builtin.set_fact:
system_cfg: >-
{{
system_cfg | combine({
'network': system_cfg.network | combine({
'bridge': _primary.bridge | default(''),
'vlan': _primary.vlan | default(''),
'ip': _primary.ip | default(''),
'prefix': _primary.prefix | default(''),
'gateway': _primary.gateway | default('')
})
}, recursive=True)
}}
- name: Normalize system disks input
vars:

View File

@@ -171,8 +171,12 @@
- hypervisor_cfg.host | string | length > 0
- hypervisor_cfg.storage | string | length > 0
- system_cfg.id | string | length > 0
- system_cfg.network.bridge | string | length > 0
fail_msg: "Missing required Proxmox inputs. Define hypervisor.(url,username,password,host,storage), system.id, and system.network.bridge."
- >-
(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
@@ -187,8 +191,12 @@
- hypervisor_cfg.datacenter | string | length > 0
- hypervisor_cfg.cluster | string | length > 0
- hypervisor_cfg.storage | string | length > 0
- system_cfg.network.bridge | string | length > 0
fail_msg: "Missing required VMware inputs. Define hypervisor.(url,username,password,datacenter,cluster,storage) and system.network.bridge."
- >-
(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
@@ -197,8 +205,10 @@
- hypervisor_type == "xen"
ansible.builtin.assert:
that:
- system_cfg.network.bridge | string | length > 0
fail_msg: "Missing required Xen inputs. Define system.network.bridge."
- >-
(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
@@ -329,3 +339,15 @@
- (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 }}"