#!/usr/bin/env bash # Test YANG ANYDATA: # Also Test CLICON_YANG_UNKNOWN_ANYDATA: Treat unknown XML/JSON nodes as anydata. # Test matrix is three dimensions: # 1. YANG spec: Add elements denotend with "u" which are either a) defined as anydata or b) unknown # 2. Make access to elements as: a) top-level, b) in container, c) in list # 3. data is in a) startup b) netconf 3) state # Load an XML file with unknown yang constructs that is labelled as anydata # Ensure clixon is robust to handle that # Test is that unknown XML subcomponents (with label u) are loaded in an xml file. # 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 test -d $dir/yang || mkdir $dir/yang cfg=$dir/conf_yang.xml fanydata=$dir/yang/anydata.yang funknown=$dir/yang/unknown.yang fstate=$dir/state.xml cat < $fanydata module any{ yang-version 1.1; prefix any; namespace "urn:example:any"; container ca{ list b{ key k; leaf k { type string; } anydata u3; } anydata u2; } anydata u1; container sa{ config false; list sb{ key k; leaf k { type string; } anydata u5; } anydata u4; } rpc myrpc { input { anydata u7; } output { anydata u8; } } } EOF cat < $funknown module unknown{ yang-version 1.1; prefix un; namespace "urn:example:unknown"; container cu{ list b{ key k; leaf k { type string; } } } container su{ config false; list sb{ key k; leaf k { type string; } } } rpc myrpc { } } EOF # For edit config XMLA='2242a string23' XMLU='2242a string23' # Full state with unknowns STATE0='2255a string2255a string' # Partial state with unknowns removed in the unknown module STATE1='2255a string22' # Run anydata and unknown tests # From a startup db or via netconf commands as well as state data # Test both anydata and unknown # Args: # 1: bool: startup (or not) # 2: bool: treat unknown as anydata (or not) testrun() { startup=$1 unknown=$2 if $unknown; then # treat unknown as anydata or not if $startup; then # If startup XML="$XMLA$XMLU" else XML="$XMLA" unknownreply="applicationunknown-elementu1errorFailed to find YANG spec of XML node: u1 with parent: config in namespace: urn:example:unknown" fi else XML="$XMLA" unknownreply="applicationunknown -elementu1errorFailed to find YANG spec of XML node: u1 with parent: config in namespace: urn:example:unknown" fi if $startup; then # get config from startup F="ietf-netconf:startup" else F="" fi cat < $cfg $cfg /usr/local/share/clixon $dir $IETFRFC $dir/yang /usr/local/lib/$APPNAME/clispec /usr/local/lib/$APPNAME/cli /usr/local/lib/$APPNAME/netconf /usr/local/lib/$APPNAME/backend $APPNAME /usr/local/var/$APPNAME/$APPNAME.sock /usr/local/var/$APPNAME/$APPNAME.pidfile $dir false false $unknown $F EOF if $startup; then # Only positive startup test, ie dont add XMLU if unknown not treated as anyxml # and check for errors cat < $dir/startup_db $XML EOF fi if [ $BE -ne 0 ]; then new "kill old backend" sudo clixon_backend -zf $cfg if [ $? -ne 0 ]; then err fi if $startup; then new "start backend -s startup -f $cfg -- -sS $fstate" start_backend -s startup -f $cfg -- -sS $fstate else new "start backend -s init -f $cfg -- -sS $fstate" start_backend -s init -f $cfg -- -sS $fstate fi new "waiting" wait_backend fi if [ $RC -ne 0 ]; then new "kill old restconf daemon" stop_restconf_pre new "start restconf daemon" start_restconf -f $cfg fi new "wait restconf" wait_restconf if ! $startup; then # If not startup, add xml using netconf new "Put anydata" expecteof "$clixon_netconf -qf $cfg -D $DBG" 0 "$XMLA]]>]]>" "]]>]]>" new "Put unknown" expecteof "$clixon_netconf -qf $cfg -D $DBG" 0 "$XMLU]]>]]>" "$unknownreply" new "commit" expecteof "$clixon_netconf -qf $cfg -D $DBG" 0 "]]>]]>" "]]>]]>" fi new "Get candidate" expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^$XML]]>]]>$" new "Get running" expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^$XML]]>]]>$" # Add other functions, (based on previous errors), eg cli show config, cli commit. new "cli show configuration" expectpart "$($clixon_cli -1 -f $cfg show conf xml)" 0 "42" new "cli commit" expectpart "$($clixon_cli -1 -f $cfg commit)" 0 "^$" new "restconf get config" expectpart "$(curl $CURLOPTS -X GET -H "Accept: application/yang-data+xml" $RCPROTO://localhost/restconf/data?content=config)" 0 "HTTP/1.1 200 OK" "$XML" # Save partial state in state file with unknown removed (positive test) echo "$STATE1" > $fstate new "Get state (positive test)" expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^$STATE1]]>]]>" new "restconf get state(positive)" expectpart "$(curl $CURLOPTS -X GET -H "Accept: application/yang-data+xml" $RCPROTO://localhost/restconf/data?content=nonconfig)" 0 "HTTP/1.1 200 OK" "$STATE1" # full state with unknowns echo "$STATE0" > $fstate new "Get state (negative test)" expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "error-message>Failed to find YANG spec of XML node: u5 with parent: sb in namespace: urn:example:unknown. Internal error, state callback returned invalid XML from plugin: example_backend" new "restconf get state(negative)" expectpart "$(curl $CURLOPTS -X GET -H "Accept: application/yang-data+xml" $RCPROTO://localhost/restconf/data?content=nonconfig)" 0 "HTTP/1.1 412 Precondition Failed" "operation-failedu5" # RPC:s take "not-supported" as OK: syntax OK and according to mdeol, just not implemented in # server. But "unknown-element" as truly unknwon. # (Would need to add a handler to get a proper OK) new "Not supported RPC" expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "operation-not-supported" new "anydata RPC" expecteof "$clixon_netconf -qf $cfg" 0 "88]]>]]>" "operation-not-supported" new "unknown RPC" expecteof "$clixon_netconf -qf $cfg" 0 "88]]>]]>" "unknown-element" if [ $RC -ne 0 ]; then new "Kill restconf daemon" stop_restconf fi 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 sudo pkill -u root -f clixon_backend fi } new "test params: -f $cfg" new "no startup, dont treat unknown as anydata----" testrun false false new "startup, dont treat unknown as anydata----" testrun true false new "no startup, treat unknown as anydata----" testrun false true new "startup, treat unknown as anydata----" testrun true true rm -rf $dir