#!/usr/bin/env bash # Yang leafref + state tests # The difficulty here is a "leafref" in state data that references config-data. # Problem being that config-data from running needs to be mergedwith state data and filtered/cropped # correctly # # The YANG has two parts, one config part (sender-config) and one state part (sender-state) # The leafref in the sender-state part references a leaf in the sender-config part # Netconf tests are made to get state, state+config, using content attribute config/nonconfig/all # with different paths. # Using the -sS state capability of the main example, that is why CLICON_BACKEND_DIR is # /usr/local/lib/$APPNAME/backend so that the main backend plugins is included. # Note: Three runs: # 1. with state data validation and with require-instance (Invalid) # 2. with state data validation and without require-instance (OK) # 3. without state data validation and with require-instance (Wrong state data no detected) # Magic line must be first in script (see README.md) s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi APPNAME=example cfg=$dir/conf_yang.xml fstate=$dir/state.xml fyang=$dir/leafref.yang fyangno=$dir/leafrefno.yang # No require-instance cat < $cfg $cfg $dir ${YANG_INSTALLDIR} $fyang /usr/local/lib/$APPNAME/backend /usr/local/lib/$APPNAME/clispec /usr/local/lib/$APPNAME/cli $APPNAME /usr/local/var/$APPNAME/$APPNAME.sock false /usr/local/var/$APPNAME/$APPNAME.pidfile /usr/local/var/$APPNAME true false EOF # NOTE prefix "example" used in module different from "ex" used in mport of that module cat < $fyang module leafref{ yang-version 1.1; namespace "urn:example:example"; prefix ex; list sender-config{ description "Main config of senders"; key name; leaf name{ type string; } } list sender-state{ description "State referencing configured senders"; config false; key ref; leaf ref{ type leafref { path "/ex:sender-config/ex:name"; } } } } EOF # No require-instance in leafref cat < $fyangno module leafref{ yang-version 1.1; namespace "urn:example:example"; prefix ex; list sender-config{ description "Main config of senders"; key name; leaf name{ type string; } } list sender-state{ description "State referencing configured senders"; config false; key ref; leaf ref{ type leafref { path "/ex:sender-config/ex:name"; require-instance false; } } } } EOF # This is state data written to file that backend reads from (on request) cat < $fstate x EOF # First run: With validation of state callbacks new "test params: -f $cfg -- -sS $fstate" if [ $BE -ne 0 ]; then new "kill old backend" sudo clixon_backend -zf $cfg if [ $? -ne 0 ]; then err fi new "start backend -s init -f $cfg -- -sS $fstate" start_backend -s init -f $cfg -- -sS $fstate fi new "wait backend" wait_backend # Test top-level, default prefix, wrong leafref prefix and typedef path XML=$(cat < x EOF ) new "leafref config sender x" expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "$XML" "" "" new "netconf commit" expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "" "" "" # Get path=/, state vs config new "netconf get / config+state" expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "" "" "xx" new "netconf get / state-only" expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "" "" "x" new "netconf get / config-only" expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "" "" "x" # Get path=/sender-state, state vs config new "netconf get /sender-state config+state" expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "" "" "x" new "netconf get /sender-state state-only" expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "" "" "x" new "netconf get /sender-state config-only" expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "" "" "" # Get path=/sender-config, state vs config new "netconf get /sender-config config+state" expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "" "" "x" new "netconf get /sender-config state-only" expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "" "" "" new "netconf get /sender-config config-only" expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "" "" "x" # Negative tests, # Double xmlns attribute cat < $fstate x EOF new "Merge same tree - check double xmlns attribute" expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "" "" "x" # Back to original cat < $fstate x EOF # delete x, add y XML=$(cat < x y EOF ) # Negative tests, start with remove x and and add y instead new "leafref config delete sender x add y" expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "$XML" "" "" new "netconf commit" expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "" "" "" # Leafref wrong internal: state references x but config contains only y new "netconf get / config+state should fail" expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "" "applicationoperation-failedxerrorLeafref validation failed: No leaf x matching path /ex:sender-config/ex:name in leafref.yang:[0-9]*. Internal error, state callback returned invalid XML" "" new "netconf get / state-only should fail" expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "" "applicationoperation-failedxerrorLeafref validation failed: No leaf x matching path /ex:sender-config/ex:name in leafref.yang:[0-9]*. Internal error, state callback returned invalid XML" "" new "netconf get / config-only ok" expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "" "" "y" if [ $BE -ne 0 ]; then new "Kill backend" # Check if premature kill pid=$(pgrep -u root -f clixon_backend) if [ -z "$pid" ]; then err "backend already dead" fi # kill backend stop_backend -f $cfg fi # Second run: Validation and no require-instance new "Second run: -f $cfg -o CLICON_YANG_MAIN_FILE=$fyangno -- -sS $fstate" if [ $BE -ne 0 ]; then new "kill old backend" sudo clixon_backend -zf $cfg if [ $? -ne 0 ]; then err fi new "start backend -s init -f $cfg -o CLICON_VALIDATE_STATE_XML=false -- -sS $fstate" start_backend -s init -f $cfg -o CLICON_YANG_MAIN_FILE=$fyangno -- -sS $fstate fi new "wait backend" wait_backend # Add y XML=$(cat < y EOF ) # Reference (non-existing) x cat < $fstate x EOF new "leafref config sender x" expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "$XML" "" "" new "netconf commit" expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "" "" "" # Leafref wrong internal: state references x but config contains only y new "netconf get / config+state wrong state xml but no validation" expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "" "" "yx" new "netconf get / state-only wrong state xml but no validation" expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "" "" "x" if [ $BE -ne 0 ]; then new "Kill backend" # Check if premature kill pid=$(pgrep -u root -f clixon_backend) if [ -z "$pid" ]; then err "backend already dead" fi # kill backend stop_backend -f $cfg fi # Third run: No validation of state callbacks new "Third run: -f $cfg -o CLICON_VALIDATE_STATE_XML=true -- -sS $fstate" if [ $BE -ne 0 ]; then new "kill old backend" sudo clixon_backend -zf $cfg if [ $? -ne 0 ]; then err fi new "start backend -s init -f $cfg -o CLICON_VALIDATE_STATE_XML=false -- -sS $fstate" start_backend -s init -f $cfg -o CLICON_VALIDATE_STATE_XML=false -- -sS $fstate fi new "wait backend" wait_backend # Add y XML=$(cat < y EOF ) # Reference (non-existing) x cat < $fstate x EOF new "leafref config sender x" expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "$XML" "" "" new "netconf commit" expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "" "" "" # Leafref wrong internal: state references x but config contains only y new "netconf get / config+state wrong state xml but no validation" expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "" "" "yx" new "netconf get / state-only wrong state xml but no validation" expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "" "" "x" if [ $BE -ne 0 ]; then new "Kill backend" # Check if premature kill pid=$(pgrep -u root -f clixon_backend) if [ -z "$pid" ]; then err "backend already dead" fi # kill backend stop_backend -f $cfg fi rm -rf $dir new "endtest" endtest