module

Krikri::PluginHelpers::IptablesCommand

Pure rule-construction/command-building/validation logic for plugins/iptables.cr, split out so it can be unit-tested without a real iptables binary/root (-C/-A/-D all require CAP_NET_ADMIN, unavailable in the spec sandbox - see plugins/iptables.cr's own doc comment). Mirrors Ansible's construct_rule() flag-for-flag, including its exact ordering (matters for -C to actually match what -A would insert), its push_arguments() command framing (rule_num only on -I, -w after the action, --numeric only on the -L call sites), and its argument-spec validation messages (mutually_exclusive / required_if / required_by wording from the Ansible module).

construct_rule() returns RAW tokens, exactly like Ansible's own: values as given, no quoting - the registered rule string is Ansible's ' '.join(construct_rule(params)) (probe-verified: a comment value reaches it unquoted, words joined with plain spaces). Quoting exists only when the exec command string is built (push_arguments shell-quotes each token so the /bin/bash -c framing keeps every value ONE argument, the way Ansible's run_command passes its argv list); push_arguments with for_display: true returns the raw space-join that Ansible's _clean_args puts in a failure's cmd.

Constants

CHOICES_BY_PARAM = {"table" => ["filter", "nat", "mangle", "raw", "security"], "state" => ["absent", "present"], "action" => ["append", "insert"], "ip_version" => ["ipv4", "ipv6", "both"], "syn" => ["ignore", "match", "negate"], "policy" => ["ACCEPT", "DROP", "QUEUE", "RETURN"], "match_set_flags" => ["src", "dst", "src,dst", "dst,src", "src,src", "dst,dst"], "log_level" => ["0", "1", "2", "3", "4", "5", "6", "7", "emerg", "alert", "crit", "error", "warning", "notice", "info", "debug"]}

Ansible's argument-spec validation for this module, message-for-message (the Ansible module wording), in its own evaluation order: mutually_exclusive (which Ansible checks BEFORE applying defaults, so only an explicitly passed flush: counts), then the per-parameter choices, then required_if, then required_by. Returns the failure message, or nil when everything passes.

CHOICES_BY_PARAM: the argument_spec's own choices lists, in the module's declaration order (the failure message echoes that order). Real-Ansible position pinned empirically: a mutually-exclusive pair fires before choices (flush + policy=DENY reports the mutual exclusion), but choices fire before required_if (state=enabled with no chain reports the choice, not the missing chain).

Class methods

construct_rule(params : Hash(String, String)) : Array(String) | String

Real-Ansible parameter order, flag-for-flag (construct_rule()). Returns the flag list, or a real-Ansible failure message when building it raises the way Python does - see the two quirks noted inline below.

Source
push_arguments(bin : String, action : String, chain : String | Nil, table : String, rule : Array(String) = [] of String, rule_num : String | Nil = nil, wait : String | Nil = nil, numeric : Bool = false, for_display : Bool = false) : String

Ansible's push_arguments(): everything it builds (the -C check, -A/-I/-D applies, the -F/-P/-L/-N/-X chain/policy operations) shares this framing - -t table, action, chain, the insert position (only on -I), then -w wait, then the rule flags. numeric is appended only by the -L call sites (get_chain_policy/check_chain_present).

The rule tokens arrive RAW (see construct_rule); the exec string shell-quotes each one with Shell.quote_arg - unlike quote_if_needed it treats whitespace as unsafe, so a multi-word value (comment, set_counters "10 20") stays ONE argument, matching Ansible's run_command argv list (which passes each value as a single element, whatever it contains). With for_display the raw tokens are space-joined instead, byte-identical to Ansible's ' '.join(...) rule string and _clean_args failure cmd.

Source
validate(params : Hash(String, String)) : String | Nil
Source