Krikri::PluginHelpers::AclCommand
Command construction + output parsing for the acl plugin (POSIX ACL management via getfacl(1)/setfacl(1)) - split out from plugins/acl.cr so it can be unit-tested without a real ACL-capable filesystem or superuser (mirrors the ufw/iptables split). Every shape here is ported field-for-field from real ansible.posix's own acl.py (build_command/split_entry/build_entry/acl_changed/run_acl) and cross-checked against the actual setfacl 2.3.2 --test output (see spec/unit/acl_command_spec.cr's notes).
Class methods
Builds the argv for one getfacl/setfacl invocation - mirrors
real acl.py's build_command, including the exact flag ordering
real Ansible produces (which matters: -d is inserted right
after the binary name, and everything else appends). Linux
only, matching this engine's Linux-target binaries - the real
module's FreeBSD -h branch (and its non-Linux fail) is not
represented. mode is "set" | "rm" | "get".
Builds the -m/-x entry argument - mirrors real acl.py's
build_entry. For POSIX ACLs the permissions section is omitted
entirely when nil (the state: absent form - -x user:joe), for
NFSv4 ACLs the 'A' ACE form with the 'tcy' type suffix is built
instead, and the group etype gets the 'g' flag in that form.
The idempotency check, ported from real acl.py's acl_changed:
setfacl --test prints the would-be result of the operation,
ending the line with *,* when nothing would change and with a
full entry list (ending ,*) when it would. So for POSIX ACLs
ANY line that does not end with *,* means changed. (FreeBSD's
always-true branch is omitted - Linux only, see build_command.)
For NFSv4 ACLs the heuristic is different: the tested-new entry
is listed twice when it already exists and once when it would
genuinely be added.
run_acl's line filtering, in a pure form (real acl.py drops any
line starting with '#', strips each remaining line, then trims a
single trailing empty line - blank separator lines BETWEEN
entries survive, which is what real Ansible's recursive acl
return value looks like).
Splits an entry: shorthand string into its parts - mirrors
real acl.py's split_entry: an optional leading d/default
section (when the entry starts with a 'd') marks a default ACL
entry, and an entry with only two ':'-separated sections (the
state: absent form, e.g. user:joe) gets a nil permissions
slot. The etype is normalized by its first letter, exactly like
the real module - anything else becomes nil (which then flows
through to setfacl as-is and fails there, matching real
Ansible's behavior for a garbage entry string).