* Limited support of RFC 7895 YANG Module Library to list modules:

* That is, limited support of: ietf-yang-library.yang
  * For example: `<module><name>example</name><revision/></module><module><name>ietf-restconf-monitoring</name><revision>2017-01-26</revision></module>...`
* Comply to RFC 8040 3.5.3.1 rule: api-identifier = [module-name ":"] identifier
  * The "module-name" was a no-op before.
  * This means that there was no difference between eg: GET /restconf/data/ietf-yang-library:modules-state and GET /restconf/data/XXXX:modules-state
This commit is contained in:
Olof hagsand 2018-09-22 16:30:58 +02:00
parent 0631be19cb
commit 74fc0800ae
18 changed files with 921 additions and 120 deletions

View file

@ -148,7 +148,7 @@ new "restconf DELETE whole datastore"
expecteq "$(curl -u adm1:bar -sS -X DELETE http://localhost/restconf/data)" ""
new2 "auth get"
expecteq "$(curl -u adm1:bar -sS -X GET http://localhost/restconf/data)" '{"data": null}
expecteq "$(curl -u adm1:bar -sS -X GET http://localhost/restconf/data/x)" 'null
'
new "auth set authentication config"

View file

@ -13,6 +13,7 @@ fyang=$dir/test.yang
fyangerr=$dir/err.yang
nacmfile=$dir/nacmfile
# Note filter out example_backend_nacm.so in CLICON_BACKEND_REGEXP below
cat <<EOF > $cfg
<config>
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
@ -190,7 +191,7 @@ new "restconf DELETE whole datastore"
expecteq "$(curl -u adm1:bar -sS -X DELETE http://localhost/restconf/data)" ""
new2 "auth get"
expecteq "$(curl -u adm1:bar -sS -X GET http://localhost/restconf/data)" '{"data": {"interfaces-state": {"interface": [{"name": "eth0","type": "ex:eth","if-index": 42}]}}}
expecteq "$(curl -u adm1:bar -sS -X GET http://localhost/restconf/data/ietf-interfaces:interfaces-state)" '{"interfaces-state": {"interface": [{"name": "eth0","type": "ex:eth","if-index": 42}]}}
'
new "Set x to 0"

View file

@ -67,7 +67,7 @@ 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
sudo $clixon_backend -s init -f $cfg -y $fyang # -D 1
if [ $? -ne 0 ]; then
err
@ -77,26 +77,21 @@ 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 # -D 1
sudo start-stop-daemon -S -q -o -b -x /www-data/clixon_restconf -d /www-data -c www-data -- -f $cfg -D 1
sleep 1
new "restconf tests"
# get the stream list using netconf
new "netconf event stream discovery RFC5277 Sec 3.2.5"
echo "$clixon_netconf -qf $cfg -y $fyang"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><get><filter type="xpath" selector="netconf/streams" xmlns="urn:ietf:params:xml:ns:netmod:notification"/></get></rpc>]]>]]>' '<rpc-reply><data><restconf-state><streams><stream><name>NETCONF</name><description>default NETCONF event stream</description><replay-support>false</replay-support></stream><stream><name>CLICON</name><description>Clicon logs</description><replay-support>false</replay-support></stream></streams></restconf-state></data></rpc-reply>]]>]]>'
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><get><filter type="xpath" select="netconf/streams" xmlns="urn:ietf:params:xml:ns:netmod:notification"/></get></rpc>]]>]]>' '<rpc-reply><data><netconf><streams><stream><name>NETCONF</name><description>default NETCONF event stream</description><replay-support>false</replay-support></stream><stream><name>CLICON</name><description>Clicon logs</description><replay-support>false</replay-support></stream></streams></netconf></data></rpc-reply>]]>]]>'
#expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><get><filter type="subtree"><netconf xmlns="urn:ietf:params:xml:ns:netmod:notification"><streams/></netconf></filter></get></rpc>]]>]]>' '<rpc-reply><data><netconf><streams><stream><name>NETCONF</name>'
new "netconf event stream discovery RFC8040 Sec 6.2"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><get><filter type="xpath" select="restconf-state/streams" xmlns="urn:ietf:params:xml:ns:netmod:notification"/></get></rpc>]]>]]>' '<rpc-reply><data><restconf-state><streams><stream><name>NETCONF</name><description>default NETCONF event stream</description><replay-support>false</replay-support></stream><stream><name>CLICON</name><description>Clicon logs</description><replay-support>false</replay-support></stream></streams></restconf-state></data></rpc-reply>]]>]]>'
#expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc message-id="101" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"><get><filter type="subtree"><netconf xmlns="urn:ietf:params:xml:ns:netmod:notification"><streams/></netconf></filter></get></rpc>]]>]]>' '<rpc-reply message-id="101" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"><data><netconf xmlns="urn:ietf:params:xml:ns:netmod:notification"><streams><stream><name>NETCONF</name>'
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": "CLICON","description": "Clicon logs","replay-support": false},{ "name": "NETCONF","description": "default NETCONF event stream","replay-support": false}\]}}'
# get the stream list using restconf
new "restconf GET datastore"
#expectfn "curl -s -X GET http://localhost/restconf/data/ietf-restconf-monitoring:restconf-state/streams" 0 '{"data": {"cont1": {"interface": \[{"name": "local0","type": "regular"}\]}}}'
new "netconf subscription"
#new "netconf subscription"
#expectwait "$clixon_netconf -qf $cfg -y $fyang" "<rpc><create-subscription><stream>ROUTING</stream></create-subscription></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]><notification><event>Routing notification</event></notification>]]>]]>$" 30
new "Kill restconf daemon"

View file

@ -5,7 +5,7 @@ APPNAME=example
# include err() and new() functions and creates $dir
. ./lib.sh
exit 0 # NYI
cfg=$dir/conf_yang.xml
fyang=$dir/test.yang
@ -91,6 +91,8 @@ expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><validate><source><candid
new "minmax: empty"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><edit-config><target><candidate/></target><default-operation>replace</default-operation><config><c/></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
exit # NYI
new "minmax: validate should fail"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><rpc-error/></rpc-reply>]]>]]>$"

View file

@ -135,6 +135,10 @@ if [ -z "$match" ]; then
err "$expect" "$ret"
fi
new "restconf schema resource, RFC 8040 sec 3.7 according to RFC 7895"
expecteq "$(curl -s -H 'Accept: application/yang-data+json' -G http://localhost/restconf/data/ietf-yang-library:modules-state/module=ietf-routing,2014-10-26/)" '{"module": [{"name": "ietf-routing","revision": "2014-10-26"}]}
'
new "restconf options. RFC 8040 4.1"
expectfn "curl -i -s -X OPTIONS http://localhost/restconf/data" 0 "Allow: OPTIONS,HEAD,GET,POST,PUT,DELETE"
@ -142,16 +146,23 @@ new "restconf head. RFC 8040 4.2"
expectfn "curl -s -I http://localhost/restconf/data" 0 "HTTP/1.1 200 OK"
#Content-Type: application/yang-data+json"
new2 "restconf empty rpc"
new "restconf empty rpc"
expecteq "$(curl -s -X POST -d {\"input\":{\"name\":\"\"}} http://localhost/restconf/operations/example:empty)" ""
new2 "restconf get empty config + state json"
expecteq "$(curl -sSG http://localhost/restconf/data)" '{"data": {"interfaces-state": {"interface": [{"name": "eth0","type": "ex:eth","if-index": 42}]}}}
expecteq "$(curl -sSG http://localhost/restconf/data/interfaces-state)" '{"interfaces-state": {"interface": [{"name": "eth0","type": "ex:eth","if-index": 42}]}}
'
new2 "restconf get empty config + state json with module name"
expecteq "$(curl -sSG http://localhost/restconf/data/ietf-interfaces:interfaces-state)" '{"interfaces-state": {"interface": [{"name": "eth0","type": "ex:eth","if-index": 42}]}}
'
new2 "restconf get empty config + state json with wrong module name"
expecteq "$(curl -sSG http://localhost/restconf/data/badmodule:interfaces-state)" '{"ietf-restconf:errors" : {"error": {"rpc-error": {"error-tag": "operation-failed","error-type": "protocol","error-severity": "error","error-message": "No yang node found: badmodule:interfaces-state"}}}} '
new "restconf get empty config + state xml"
ret=$(curl -s -H "Accept: application/yang-data+xml" -G http://localhost/restconf/data)
expect="<data><interfaces-state><interface><name>eth0</name><type>ex:eth</type><if-index>42</if-index></interface></interfaces-state></data>"
ret=$(curl -s -H "Accept: application/yang-data+xml" -G http://localhost/restconf/data/interfaces-state)
expect="<interfaces-state><interface><name>eth0</name><type>ex:eth</type><if-index>42</if-index></interface></interfaces-state>"
match=`echo $ret | grep -EZo "$expect"`
if [ -z "$match" ]; then
err "$expect" "$ret"
@ -184,7 +195,7 @@ if [ -z "$match" ]; then
fi
new2 "restconf GET datastore"
expecteq "$(curl -s -X GET http://localhost/restconf/data)" '{"data": {"interfaces-state": {"interface": [{"name": "eth0","type": "ex:eth","if-index": 42}]}}}
expecteq "$(curl -s -X GET http://localhost/restconf/data/interfaces-state)" '{"interfaces-state": {"interface": [{"name": "eth0","type": "ex:eth","if-index": 42}]}}
'
# Exact match
@ -201,19 +212,23 @@ new "restconf Check interfaces eth/0/0 added"
expectfn "curl -s -G http://localhost/restconf/data" 0 '{"interfaces": {"interface": \[{"name": "eth/0/0","type": "ex:eth","enabled": true}\]},"interfaces-state": {"interface": \[{"name": "eth0","type": "ex:eth","if-index": 42}\]}}
'
new2 "restconf delete interfaces"
new "restconf delete interfaces"
expecteq $(curl -s -X DELETE http://localhost/restconf/data/interfaces) ""
new "restconf Check empty config"
expectfn "curl -sG http://localhost/restconf/data" 0 "$state"
expectfn "curl -sG http://localhost/restconf/data/interfaces-state" 0 "$state"
new "restconf Add interfaces subtree eth/0/0 using POST"
expectfn 'curl -s -X POST -d {"interface":{"name":"eth/0/0","type":"ex:eth","enabled":true}} http://localhost/restconf/data/interfaces' 0 ""
# XXX cant get this to work
#expecteq "$(curl -s -X POST -d '{"interface":{"name":"eth/0/0","type\":"ex:eth","enabled":true}}' http://localhost/restconf/data/interfaces)" ""
new2 "restconf Check eth/0/0 added"
expecteq "$(curl -s -G http://localhost/restconf/data)" '{"data": {"interfaces": {"interface": [{"name": "eth/0/0","type": "ex:eth","enabled": true}]},"interfaces-state": {"interface": [{"name": "eth0","type": "ex:eth","if-index": 42}]}}}
new2 "restconf Check eth/0/0 added config"
expecteq "$(curl -s -G http://localhost/restconf/data/interfaces)" '{"interfaces": {"interface": [{"name": "eth/0/0","type": "ex:eth","enabled": true}]}}
'
new2 "restconf Check eth/0/0 added state"
expecteq "$(curl -s -G http://localhost/restconf/data/interfaces-state)" '{"interfaces-state": {"interface": [{"name": "eth0","type": "ex:eth","if-index": 42}]}}
'
new2 "restconf Re-post eth/0/0 which should generate error"
@ -226,7 +241,7 @@ new "Add nothing using POST"
expectfn 'curl -s -X POST http://localhost/restconf/data/interfaces/interface=eth%2f0%2f0' 0 '"ietf-restconf:errors" : {"error": {"rpc-error": {"error-tag": "malformed-message","error-type": "rpc","error-severity": "error","error-message": " on line 1: syntax error at or before:'
new2 "restconf Check description added"
expecteq "$(curl -s -G http://localhost/restconf/data)" '{"data": {"interfaces": {"interface": [{"name": "eth/0/0","description": "The-first-interface","type": "ex:eth","enabled": true}]},"interfaces-state": {"interface": [{"name": "eth0","type": "ex:eth","if-index": 42}]}}}
expecteq "$(curl -s -G http://localhost/restconf/data/interfaces)" '{"interfaces": {"interface": [{"name": "eth/0/0","description": "The-first-interface","type": "ex:eth","enabled": true}]}}
'
new "restconf delete eth/0/0"
@ -242,7 +257,7 @@ new "restconf Add subtree eth/0/0 using PUT"
expecteq "$(curl -s -X PUT -d '{"interface":{"name":"eth/0/0","type":"ex:eth","enabled":true}}' http://localhost/restconf/data/interfaces/interface=eth%2f0%2f0)" ""
new2 "restconf get subtree"
expecteq "$(curl -s -G http://localhost/restconf/data)" '{"data": {"interfaces": {"interface": [{"name": "eth/0/0","type": "ex:eth","enabled": true}]},"interfaces-state": {"interface": [{"name": "eth0","type": "ex:eth","if-index": 42}]}}}
expecteq "$(curl -s -G http://localhost/restconf/data/interfaces)" '{"interfaces": {"interface": [{"name": "eth/0/0","type": "ex:eth","enabled": true}]}}
'
new2 "restconf rpc using POST json"

View file

@ -69,8 +69,8 @@ new "restconf tests"
new "restconf POST initial tree"
expectfn 'curl -s -X POST -d {"cont1":{"interface":{"name":"local0","type":"regular"}}} http://localhost/restconf/data' 0 ""
new "restconf GET datastore"
expectfn "curl -s -X GET http://localhost/restconf/data" 0 '{"data": {"cont1": {"interface": \[{"name": "local0","type": "regular"}\]}}}'
new "restconf GET datastore intial"
expectfn "curl -s -X GET http://localhost/restconf/data/cont1" 0 '{"cont1": {"interface": \[{"name": "local0","type": "regular"}\]}}'
new "restconf GET interface"
expectfn "curl -s -X GET http://localhost/restconf/data/cont1/interface=local0" 0 '{"interface": \[{"name": "local0","type": "regular"}\]}'
@ -94,31 +94,31 @@ new "restconf DELETE"
expectfn 'curl -s -X DELETE http://localhost/restconf/data/cont1' 0 ""
new "restconf GET null datastore"
expectfn "curl -s -X GET http://localhost/restconf/data" 0 '{"data": null}'
expectfn "curl -s -X GET http://localhost/restconf/data/cont1" 0 'null'
new "restconf POST initial tree"
expectfn 'curl -s -X POST -d {"cont1":{"interface":{"name":"local0","type":"regular"}}} http://localhost/restconf/data' 0 ""
new "restconf GET initial tree"
expectfn "curl -s -X GET http://localhost/restconf/data" 0 '{"data": {"cont1": {"interface": \[{"name": "local0","type": "regular"}\]}}}'
expectfn "curl -s -X GET http://localhost/restconf/data/cont1" 0 '{"cont1": {"interface": \[{"name": "local0","type": "regular"}\]}}'
new "restconf DELETE whole datastore"
expectfn 'curl -s -X DELETE http://localhost/restconf/data' 0 ""
new "restconf GET null datastore"
expectfn "curl -s -X GET http://localhost/restconf/data" 0 '{"data": null}'
expectfn "curl -s -X GET http://localhost/restconf/data/cont1" 0 'null'
new "restconf PUT initial datastore"
expectfn 'curl -s -X PUT -d {"data":{"cont1":{"interface":{"name":"local0","type":"regular"}}}} http://localhost/restconf/data' 0 ""
new "restconf GET datastore"
expectfn "curl -s -X GET http://localhost/restconf/data" 0 '{"data": {"cont1": {"interface": \[{"name": "local0","type": "regular"}\]}}}'
expectfn "curl -s -X GET http://localhost/restconf/data/cont1" 0 '{"cont1": {"interface": \[{"name": "local0","type": "regular"}\]}}'
new "restconf PUT replace datastore"
expectfn 'curl -s -X PUT -d {"data":{"cont2":{"name":"foo"}}} http://localhost/restconf/data' 0 ""
new "restconf GET replaced datastore"
expectfn "curl -s -X GET http://localhost/restconf/data" 0 '{"data": {"cont2": {"name": "foo"}}}'
expectfn "curl -s -X GET http://localhost/restconf/data/cont2" 0 '{"cont2": {"name": "foo"}}'
new "restconf PUT initial datastore again"
expectfn 'curl -s -X PUT -d {"data":{"cont1":{"interface":{"name":"local0","type":"regular"}}}} http://localhost/restconf/data' 0 ""
@ -126,9 +126,8 @@ expectfn 'curl -s -X PUT -d {"data":{"cont1":{"interface":{"name":"local0","type
new "restconf PUT change interface"
expectfn 'curl -s -X PUT -d {"interface":{"name":"local0","type":"atm0"}} http://localhost/restconf/data/cont1/interface=local0' 0 ""
new "restconf GET datastore atm"
expectfn "curl -s -X GET http://localhost/restconf/data" 0 '{"data": {"cont1": {"interface": \[{"name": "local0","type": "atm0"}\]}}}'
expectfn "curl -s -X GET http://localhost/restconf/data/cont1" 0 '{"cont1": {"interface": \[{"name": "local0","type": "atm0"}\]}}'
new "restconf PUT add interface"
expectfn 'curl -s -X PUT -d {"interface":{"name":"TEST","type":"eth0"}} http://localhost/restconf/data/cont1/interface=TEST' 0 ""

View file

@ -117,6 +117,9 @@ new "cli not defined extension"
# This text yields an error, but the test cannot detect the error message yet
#expectfn "$clixon_cli -1f $cfg -y $fyangerr show version" 0 "Yang error: Extension ex:not-defined not found"
new "netconf schema resource, RFC 7895"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><get><filter type="xpath" select="modules-state/module" xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-library"/></get></rpc>]]>]]>' '<module><name>ietf-yang-library</name><revision>2016-06-21</revision></module>'
new "netconf edit config"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><edit-config><target><candidate/></target><config><x><y><a>1</a><b>2</b><c>5</c><val>one</val></y><d/></x></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
@ -140,7 +143,7 @@ new "netconf get leaf-list path"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><get-config><source><candidate/></source><filter type=\"xpath\" select=\"/x/f[e='hej']\"/></get-config></rpc>]]>]]>" "^<rpc-reply><data><x><f><e>hej</e><e>hopp</e></f></x></data></rpc-reply>]]>]]>$"
new "netconf get (should be some)"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><get><filter type=\"xpath\" select=\"/\"/></get></rpc>]]>]]>" "^<rpc-reply><data><x><y><a>1</a><b>2</b><c>5</c><val>one</val></y><d/></x></data></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><get><filter type=\"xpath\" select=\"/\"/></get></rpc>]]>]]>" "^<rpc-reply><data><x><y><a>1</a><b>2</b><c>5</c><val>one</val></y><d/></x>"
new "cli set leaf-list"
expectfn "$clixon_cli -1f $cfg -y $fyang set x f e foo" 0 ""