Split out from #3 (commit-confirmed apply), whose titled ask shipped in 2.3.0. This is the residual config-convergence item the 2.2.3 notes parked under #3: a clearing path for static-proto leftover fields that x-uapi-clear-on-omit cannot currently handle.
Background
A network/interfaces section adopted via terraform import (e.g. the box's default wan) often carries static-proto fields from its prior life: ipaddr, ipaddrs, netmask, gateway, dns. Once the managed config sets proto=dhcp those fields are inert (netifd ignores them under DHCP) but they persist in /etc/config/network, and a clean plan reports "No changes" because the provider only manages attributes present in its config. LuCI behaves identically on a proto switch, so closing this is a deliberate improvement over the platform baseline, not parity.
x-uapi-clear-on-omit (2.2.2 / 2.2.3) lets an IaC client clear caller-owned fields the operator omits. netmask and gateway carry it and read back null cleanly. ipaddr / ipaddrs / dns cannot, for shape reasons:
ipaddr is derived from ipaddrs; the two alias to the same uci key.
ipaddrs uses as_list(), which returns [] for an absent key, not null.
dns has the same as_list() empty-list coercion.
A plain-Optional Terraform attribute MUST read back null when config omits it; [] or an aliased value fails the apply with "Provider produced inconsistent result after apply." So these three need a different clearing mechanism than the section.X ?? null clear-on-omit shape.
Options sketched on #3
- Provider-side (smallest): on interface create/update the provider sends explicit nulls for schema fields absent from config, at minimum the ones not valid for the section's current proto. The curated schemas already encode which fields belong to which proto. This puts the strictness where the declarative-intent model already lives; OpenWrt does not enforce "a section contains exactly its current-proto fields" as a platform invariant, so it keeps uapi from being stricter than the platform.
- Server-side prune: a "this section should contain exactly these options" mode in uapi. Stricter than the platform, and needs care not to clobber operator-set fields uapi does not curate.
Related, separate shape (not this issue)
Leftover whole sections the managed set never references (left behind on the box) are the part Terraform genuinely cannot model from outside, since it has no way to know an unmanaged section exists. That is a distinct "reason about the full package" concern and wants its own issue if pursued.
Split out from #3 (commit-confirmed apply), whose titled ask shipped in 2.3.0. This is the residual config-convergence item the 2.2.3 notes parked under #3: a clearing path for static-proto leftover fields that
x-uapi-clear-on-omitcannot currently handle.Background
A
network/interfacessection adopted viaterraform import(e.g. the box's defaultwan) often carries static-proto fields from its prior life:ipaddr,ipaddrs,netmask,gateway,dns. Once the managed config setsproto=dhcpthose fields are inert (netifd ignores them under DHCP) but they persist in/etc/config/network, and a clean plan reports "No changes" because the provider only manages attributes present in its config. LuCI behaves identically on a proto switch, so closing this is a deliberate improvement over the platform baseline, not parity.x-uapi-clear-on-omit(2.2.2 / 2.2.3) lets an IaC client clear caller-owned fields the operator omits.netmaskandgatewaycarry it and read backnullcleanly.ipaddr/ipaddrs/dnscannot, for shape reasons:ipaddris derived fromipaddrs; the two alias to the same uci key.ipaddrsusesas_list(), which returns[]for an absent key, notnull.dnshas the sameas_list()empty-list coercion.A plain-Optional Terraform attribute MUST read back
nullwhen config omits it;[]or an aliased value fails the apply with "Provider produced inconsistent result after apply." So these three need a different clearing mechanism than thesection.X ?? nullclear-on-omit shape.Options sketched on #3
Related, separate shape (not this issue)
Leftover whole sections the managed set never references (left behind on the box) are the part Terraform genuinely cannot model from outside, since it has no way to know an unmanaged section exists. That is a distinct "reason about the full package" concern and wants its own issue if pursued.