#!/usr/bin/env bash # yang augment and identityref tests in different modules # See RFC7950 Sec 7.17 # This test defines an example-augment module which augments an interface # defined in ietf-interface module. The interface then consists of identities # both defined in the basic ietf-interfaces module (type) as well as the main # module through the augmented module () # The ietf-interfaces is very restricted (not original). # From a namespace perspective, there are two modules, with symbols as follows: # 1. ietf-interface - urn:ietf:params:xml:ns:yang:ietf-interfaces # interfaces, interface, name, type # 2. example-augment - urn:example:augment - mymod # (augmented): mandatory-leaf, me, other, # (uses/grouping): ip, port, lid, lport # Note augment+state not tested here (need plugin), simple test in test_restconf.sh # # 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 fyang=$dir/main.yang fyang2=$dir/ietf-interfaces@2019-03-04.yang # Define default restconfig config: RESTCONFIG RESTCONFIG=$(restconf_config none false) cat < $cfg $cfg a:test clixon-restconf:allow-auth-none $dir /usr/local/share/clixon $fyang /usr/local/lib/$APPNAME/clispec /usr/local/lib/$APPNAME/cli $APPNAME /usr/local/var/$APPNAME/$APPNAME.sock /usr/local/var/$APPNAME/$APPNAME.pidfile /usr/local/var/$APPNAME true $RESTCONFIG EOF # Stub ietf-interfaces for test # This is the target module (where the augment is applied to) # The grouping is from rfc7950 Sec 7.12 with simplified types cat < $fyang2 module ietf-interfaces { yang-version 1.1; namespace "urn:ietf:params:xml:ns:yang:ietf-interfaces"; prefix if; revision "2019-03-04"; identity interface-type { description "Base identity from which specific interface types are derived."; } identity fddi { base interface-type; } container interfaces { description "Interface parameters."; list interface { key "name"; leaf name { type string; } leaf type { type identityref { base interface-type; } mandatory true; } } } grouping endpoint { description "A reusable endpoint group. From rf7950 Sec 7.12.2"; leaf ip { type string; } leaf port { type uint16; } } /* Original choice that gets augmented */ choice target { case stream { leaf one{ type string; } } } notification started { leaf id{ type string; } } } EOF # From rfc7950 sec 7.17 # This is the main module where the augment exists cat < $fyang module example-augment { yang-version 1.1; namespace "urn:example:augment"; prefix mymod; import ietf-interfaces { prefix if; } revision "2019-03-04"; identity some-new-iftype { base if:interface-type; } identity my-type { description "an identity based in the main module"; } identity you { base my-type; } grouping localgroup { description "Local grouping defining lid and lport"; leaf lid { description "this will be kept as-is"; type string; } leaf lport { description "this will be refined"; type uint16; } } augment "/if:interfaces/if:interface" { when 'derived-from-or-self(if:type, "mymod:some-new-iftype")'; container ospf { /* moved from test_restconf_err (two-level augment) */ leaf reference-bandwidth { type uint32; } } leaf mandatory-leaf { mandatory true; type string; } leaf me { type identityref { base mymod:my-type; } } leaf other { type identityref { base if:interface-type; } } uses if:endpoint { description "Use an external grouping defining ip and port"; refine port { default 80; } refine ip { description "double refine triggered mem error"; } } uses localgroup { description "Use a local grouping defining lip and lport"; refine lport { default 8080; } } } /* augment choice */ augment "/if:target" { case datastore { leaf two{ type uint32; } } } /* augment notification */ augment "/if:started" { leaf argument{ type string; } } } EOF new "test params: -f $cfg" 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" start_backend -s init -f $cfg fi new "wait backend" wait_backend 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 # mandatory-leaf See RFC7950 Sec 7.17 new "netconf set interface with augmented type and mandatory leaf" expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO e1 mymod:some-new-iftype true ]]>]]>" "^]]>]]>$" new "netconf verify get with refined ports" expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO]]>]]>" "^e1mymod:some-new-iftypetrue808080" new "netconf set identity defined in other" expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO e2 mymod:some-new-iftype true if:fddi ]]>]]>" "^]]>]]>$" new "netconf validate ok" expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO]]>]]>" "^]]>]]>$" new "netconf set identity defined in main" expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO e3 mymod:some-new-iftype true mymod:you ]]>]]>" "^]]>]]>$" new "netconf commit ok" expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO]]>]]>" "^]]>]]>$" # restconf and augment new "restconf get augment json" expectpart "$(curl $CURLOPTS -X GET $RCPROTO://localhost/restconf/data/ietf-interfaces:interfaces)" 0 "HTTP/$HVER 200" '{"ietf-interfaces:interfaces":{"interface":\[{"name":"e1","type":"example-augment:some-new-iftype","example-augment:mandatory-leaf":"true","example-augment:port":80,"example-augment:lport":8080},{"name":"e2","type":"example-augment:some-new-iftype","example-augment:mandatory-leaf":"true","example-augment:other":"ietf-interfaces:fddi","example-augment:port":80,"example-augment:lport":8080},{"name":"e3","type":"example-augment:some-new-iftype","example-augment:mandatory-leaf":"true","example-augment:me":"you","example-augment:port":80,"example-augment:lport":8080}\]}}' new "restconf get augment xml" expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+xml' $RCPROTO://localhost/restconf/data/ietf-interfaces:interfaces)" 0 "HTTP/$HVER 200" ' e1mymod:some-new-iftypetrue808080e2mymod:some-new-iftypetrueif:fddi808080e3mymod:some-new-iftypetruemymod:you808080' #e123' XML=$(cat <e1mymod:some-new-iftypetrue23 EOF ) # XXX: Since derived-from etc are NOT implemented, this test may have false positives # revisit when it is implemented. new "restconf PUT augment multi-namespace path e1 (whole path)" expectpart "$(curl $CURLOPTS -X PUT -H 'Content-Type: application/yang-data+xml' $RCPROTO://localhost/restconf/data/ietf-interfaces:interfaces/interface=e1 -d "$XML")" 0 "HTTP/$HVER 204" XML=$(cat <23 EOF ) new "restconf POST augment multi-namespace path e2 (middle path)" expectpart "$(curl $CURLOPTS -X POST -H 'Content-Type: application/yang-data+xml' $RCPROTO://localhost/restconf/data/ietf-interfaces:interfaces/interface=e2 -d "$XML" )" 0 "HTTP/$HVER 201" new "restconf GET augment multi-namespace top" expectpart "$(curl $CURLOPTS -X GET $RCPROTO://localhost/restconf/data/ietf-interfaces:interfaces)" 0 "HTTP/$HVER 200" '{"ietf-interfaces:interfaces":{"interface":\[{"name":"e1","type":"example-augment:some-new-iftype","example-augment:ospf":{"reference-bandwidth":23},"example-augment:mandatory-leaf":"true","example-augment:port":80,"example-augment:lport":8080},{"name":"e2","type":"example-augment:some-new-iftype","example-augment:ospf":{"reference-bandwidth":23},"example-augment:mandatory-leaf":"true","example-augment:other":"ietf-interfaces:fddi","example-augment:port":80,"example-augment:lport":8080},{"name":"e3","type":"example-augment:some-new-iftype","example-augment:mandatory-leaf":"true","example-augment:me":"you","example-augment:port":80,"example-augment:lport":8080}\]}}' new "restconf GET augment multi-namespace level 1" expectpart "$(curl $CURLOPTS -X GET $RCPROTO://localhost/restconf/data/ietf-interfaces:interfaces/interface=e1)" 0 "HTTP/$HVER 200" '{"ietf-interfaces:interface":\[{"name":"e1","type":"example-augment:some-new-iftype","example-augment:ospf":{"reference-bandwidth":23},"example-augment:mandatory-leaf":"true","example-augment:port":80,"example-augment:lport":8080}\]}' new "restconf GET augment multi-namespace cross" expectpart "$(curl $CURLOPTS -X GET $RCPROTO://localhost/restconf/data/ietf-interfaces:interfaces/interface=e1/example-augment:ospf)" 0 "HTTP/$HVER 200" '{"example-augment:ospf":{"reference-bandwidth":23}}' new "restconf GET augment multi-namespace cross level 2" expectpart "$(curl $CURLOPTS -X GET $RCPROTO://localhost/restconf/data/ietf-interfaces:interfaces/interface=e1/example-augment:ospf/reference-bandwidth)" 0 "HTTP/$HVER 200" '{"example-augment:reference-bandwidth":23}' 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 fi # Set by restconf_config unset RESTCONFIG rm -rf $dir new "endtest" endtest