linkd

Control plane daemon for unos
git clone git://git.finwo.net/app/linkd
Log | Files | Refs | README

test_plugin.sh (4006B)


      1 #!/bin/sh
      2 # Plugin subsystem: handshake, config delivery, broadcast, failure semantics.
      3 #
      4 # Driven by tests/fixtures/plugin-echo.sh, a plugin written in POSIX shell.
      5 # That is deliberate: if the suite passes with a shell plugin, the claim that
      6 # plugins need no particular language is tested rather than asserted.
      7 set -eu
      8 HERE=$(cd "$(dirname "$0")" && pwd)
      9 ROOT=$(cd "${HERE}/../.." && pwd)
     10 . "${HERE}/../helpers.sh"
     11 
     12 echo "==> test_plugin: RESP plugin subsystem"
     13 
     14 BUILD_DIR=$(ensure_built "${ROOT}")
     15 BIN="${BUILD_DIR}/linkd"
     16 FIXTURE="${ROOT}/tests/fixtures/plugin-echo.sh"
     17 assert_path_exists "${FIXTURE}" "shell plugin fixture present"
     18 
     19 T=$(mktemp -d)
     20 trap 'rm -rf "${T}"' EXIT
     21 mkdir -p "${T}/net"
     22 
     23 # No `auto`: nothing is applied, so the daemon needs no CAP_NET_ADMIN and
     24 # cannot modify the host. The plugin still sees real PORT/RIF/NEIGH events,
     25 # because the startup resync dumps the interfaces that already exist -- and
     26 # reading them is unprivileged.
     27 cat > "${T}/net/interfaces" <<EOF
     28 iface lo
     29     address 127.0.0.1/8
     30 EOF
     31 
     32 cat > "${T}/net/ports" <<EOF
     33 port swp1
     34     speed 25000
     35     fec rs
     36     autoneg 0
     37 EOF
     38 
     39 # Runs linkd to completion against a config, returning its log.
     40 run_linkd() {
     41   # run_linkd <config> [env assignments...]
     42   _cfg=$1; shift
     43   env "$@" PLUGIN_LOG="${T}/plugin.log" \
     44     timeout 15 "${BIN}" --config "${_cfg}" --resync-interval 0 \
     45     >"${T}/linkd.log" 2>&1 || true
     46   cat "${T}/linkd.log"
     47 }
     48 
     49 # --- handshake + config delivery -------------------------------------------
     50 cat > "${T}/full.cnf" <<EOF
     51 config_iface ${T}/net/interfaces
     52 config_ports ${T}/net/ports
     53 listen unix://${T}/linkd.sock
     54 plugin ${FIXTURE}
     55     echo-setting value1 value2
     56 EOF
     57 
     58 : > "${T}/plugin.log"
     59 run_linkd "${T}/full.cnf" >/dev/null
     60 
     61 assert_file_contains "${T}/plugin.log" "COMMAND"     "plugin asked for COMMAND"
     62 assert_file_contains "${T}/plugin.log" "INFO"        "plugin asked for INFO"
     63 assert_file_contains "${T}/plugin.log" "CONFIG LIST" "plugin asked for CONFIG LIST"
     64 assert_file_contains "${T}/plugin.log" "CONFIG SET echo-setting value1 value2" \
     65   "unknown sub-directive delivered as CONFIG SET"
     66 
     67 # Operations reach the plugin in the documented subcommand form.
     68 assert_file_contains "${T}/plugin.log" "PORT APPLY swp1 speed 25000 fec rs autoneg 0" \
     69   "ports config broadcast as PORT APPLY"
     70 assert_file_contains "${T}/plugin.log" "PORT ADMIN lo up" "netlink link event broadcast"
     71 assert_file_contains "${T}/plugin.log" "RIF ADD lo 127.0.0.1/8" "address event broadcast as RIF ADD"
     72 
     73 # --- hardware_detected gates the plugin ------------------------------------
     74 : > "${T}/plugin.log"
     75 out=$(run_linkd "${T}/full.cnf" PLUGIN_HARDWARE=0)
     76 assert_contains "${out}" "no supported hardware" "plugin reporting no hardware is refused"
     77 
     78 # --- failure semantics ------------------------------------------------------
     79 # A required plugin failing an operation fails that operation.
     80 : > "${T}/plugin.log"
     81 out=$(run_linkd "${T}/full.cnf" PLUGIN_FAIL_VERB=PORT)
     82 assert_contains "${out}" "port_admin lo failed" "required plugin failure fails the operation"
     83 
     84 # The same plugin marked optional does not.
     85 cat > "${T}/opt.cnf" <<EOF
     86 config_iface ${T}/net/interfaces
     87 listen unix://${T}/linkd.sock
     88 plugin ${FIXTURE}
     89     optional
     90 EOF
     91 : > "${T}/plugin.log"
     92 out=$(run_linkd "${T}/opt.cnf" PLUGIN_FAIL_VERB=PORT)
     93 case "${out}" in
     94   *"port_admin lo failed"*)
     95     echo "FAIL: optional plugin failure still failed the operation" >&2; exit 1 ;;
     96   *"deliberate failure"*)
     97     echo "PASS: optional plugin failure logged but not fatal" ;;
     98   *)
     99     echo "FAIL: optional plugin was not consulted at all" >&2; exit 1 ;;
    100 esac
    101 
    102 # --- no plugins configured --------------------------------------------------
    103 cat > "${T}/none.cnf" <<EOF
    104 config_iface ${T}/net/interfaces
    105 listen unix://${T}/linkd.sock
    106 EOF
    107 out=$(run_linkd "${T}/none.cnf")
    108 case "${out}" in
    109   *"ERROR"*plugin*) echo "FAIL: plugin errors without any plugin configured" >&2; exit 1 ;;
    110   *) echo "PASS: no plugins configured is not an error" ;;
    111 esac
    112 
    113 echo "==> test_plugin done"