#!/bin/bash # Tests for event streams using notifications # Assumptions: # 1. http server setup, such as nginx described in apps/restconf/README.md # especially SSE - ngchan setup # 2. Example stream as Clixon example which needs registration, callback and # notification generating code APPNAME=example # include err() and new() functions and creates $dir . ./lib.sh cfg=$dir/conf.xml fyang=$dir/stream.yang xml=$dir/xml.xml # example cat < $cfg $cfg /usr/local/share/clixon false /usr/local/var/$APPNAME/$APPNAME.sock /usr/local/lib/$APPNAME/backend example_backend.so$ $dir/restconf.pidfile /usr/local/var/$APPNAME /usr/local/lib/xmldb/text.so /usr/local/lib/$APPNAME/clispec /usr/local/lib/$APPNAME/cli $APPNAME true true true streams https://localhost EOF # RFC5277 NETCONF Event Notifications # using reportingEntity (rfc5277) not reporting-entity (rfc8040) cat < $fyang module example { namespace "http://example.com/event/1.0"; prefix ex; organization "Example, Inc."; contact "support at example.com"; description "Example Notification Data Model Module."; revision "2016-07-07" { description "Initial version."; reference "example.com document 2-9976."; } notification event { description "Example notification event."; leaf event-class { type string; description "Event class identifier."; } container reportingEntity { description "Event specific information."; leaf card { type string; description "Line card identifier."; } } leaf severity { type string; description "Event severity description."; } } container state { config false; description "state data for the example application (must be here for example get operation)"; leaf-list op { type string; } } } EOF # kill old backend (if any) new "kill old backend" sudo clixon_backend -zf $cfg if [ $? -ne 0 ]; then err fi new "start backend -s init -f $cfg -y $fyang" sudo $clixon_backend -s init -f $cfg -y $fyang # -D 1 if [ $? -ne 0 ]; then err fi new "kill old restconf daemon" sudo pkill -u www-data clixon_restconf new "start restconf daemon" sudo start-stop-daemon -S -q -o -b -x /www-data/clixon_restconf -d /www-data -c www-data -- -f $cfg -y $fyang # -D 1 new "netconf event stream discovery RFC5277 Sec 3.2.5" expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 ']]>]]>' 'EXAMPLEExample event streamfalse]]>]]>' new "netconf event stream discovery RFC8040 Sec 6.2" expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 ']]>]]>' 'EXAMPLEExample event streamfalsexmlhttps://localhost/streams/EXAMPLE]]>]]>' new "restconf event stream discovery RFC8040 Sec 6.2" expectfn "curl -s -X GET http://localhost/restconf/data/ietf-restconf-monitoring:restconf-state/streams" 0 '{"streams": {"stream": \[{"name": "EXAMPLE","description": "Example event stream","replay-support": false,"access": \[{"encoding": "xml","location": "https://localhost/streams/EXAMPLE"}\]}\]}' new "restconf subscribe RFC8040 Sec 6.3, get location" expectfn "curl -s -X GET http://localhost/restconf/data/ietf-restconf-monitoring:restconf-state/streams/stream=EXAMPLE/access=xml/location" 0 '{"location": "https://localhost/streams/EXAMPLE"}' # Restconf stream subscription RFC8040 Sec 6.3 - Native solution new "restconf monitor event nonexist stream" expectwait 'curl -s -X GET -H "Accept: text/event-stream" -H "Cache-Control: no-cache" -H "Connection: keep-alive" http://localhost/streams/NOTEXIST' 0 'invalid-valueapplicationerrorNo such stream' 2 # Need manual testing new "restconf monitor streams native NEEDS manual testing" if false; then # url -H "Accept: text/event-stream" http://localhost/streams/EXAMPLE # Expect: # data: 2018-10-21T19:22:11.381827faultEthernet0major # # data: 2018-10-21T19:22:16.387228faultEthernet0major new "restconf monitor event ok stream" expectwait 'curl -s -X GET -H "Accept: text/event-stream" -H "Cache-Control: no-cache" -H "Connection: keep-alive" http://localhost/streams/EXAMPLE' 0 'foo' 2 fi # Restconf stream subscription RFC8040 Sec 6.3 - Nginx nchan solution # Need manual testing new "restconf monitor streams nchan NEEDS manual testing" if false; then # url -H "Accept: text/event-stream" http://localhost/streams/EXAMPLE # Expect: echo foo fi # Netconf stream subscription # Switch here since subscriptions takes time if true; then new "netconf EXAMPLE subscription" expectwait "$clixon_netconf -qf $cfg -y $fyang" 'EXAMPLE]]>]]>' '^]]>]]>20' 5 new "netconf EXAMPLE subscription with simple filter" expectwait "$clixon_netconf -qf $cfg -y $fyang" "EXAMPLE]]>]]>" '^]]>]]>20' 5 new "netconf EXAMPLE subscription with filter classifier" expectwait "$clixon_netconf -qf $cfg -y $fyang" "EXAMPLE]]>]]>" '^]]>]]>20' 5 new "netconf NONEXIST subscription" expectwait "$clixon_netconf -qf $cfg -y $fyang" 'NONEXIST]]>]]>' '^invalid-valueapplicationerrorNo such stream]]>]]>$' 5 fi new "netconf EXAMPLE subscription with wrong date" expectwait "$clixon_netconf -qf $cfg -y $fyang" 'EXAMPLEkallekaka]]>]]>' '^bad-elementapplicationstartTimeerrorExpected timestamp]]>]]>$' 0 new "netconf EXAMPLE subscription with replay" NOW=$(date +"%Y-%m-%dT%H:%M:%S") sleep 10 expectwait "$clixon_netconf -qf $cfg -y $fyang" "EXAMPLE$NOW]]>]]>" '^]]>]]>20' 10 new "Kill restconf daemon" sudo pkill -u www-data clixon_restconf new "Kill backend" # kill backend sudo clixon_backend -zf $cfg if [ $? -ne 0 ]; then err "kill backend" fi # Check if still alive pid=`pgrep clixon_backend` if [ -n "$pid" ]; then sudo kill $pid fi rm -rf $dir