diff --git a/apps/restconf/restconf_methods_get.c b/apps/restconf/restconf_methods_get.c index 9161c9e8..2059666c 100644 --- a/apps/restconf/restconf_methods_get.c +++ b/apps/restconf/restconf_methods_get.c @@ -124,6 +124,7 @@ api_data_get2(clicon_handle h, cxobj *xtop = NULL; cxobj *xbot = NULL; yang_stmt *y = NULL; + char *with_defaults = NULL; clicon_debug(1, "%s", __FUNCTION__); if ((yspec = clicon_dbspec_yang(h)) == NULL){ @@ -194,8 +195,13 @@ api_data_get2(clicon_handle h, } } } + if ((attr = cvec_find_str(qvec, "with-defaults")) != NULL){ + clicon_debug(1, "%s with_defaults=%s", __FUNCTION__, attr); + with_defaults = attr; + } + clicon_debug(1, "%s path:%s", __FUNCTION__, xpath); - ret = clicon_rpc_get(h, xpath, nsc, content, depth, &xret); + ret = clicon_rpc_get2(h, xpath, nsc, content, depth, with_defaults, &xret); if (ret < 0){ if (netconf_operation_failed_xml(&xerr, "protocol", clicon_err_reason) < 0) diff --git a/lib/clixon/clixon_proto_client.h b/lib/clixon/clixon_proto_client.h index 846bec68..4fafae31 100644 --- a/lib/clixon/clixon_proto_client.h +++ b/lib/clixon/clixon_proto_client.h @@ -54,6 +54,7 @@ int clicon_rpc_copy_config(clicon_handle h, char *db1, char *db2); int clicon_rpc_delete_config(clicon_handle h, char *db); int clicon_rpc_lock(clicon_handle h, char *db); int clicon_rpc_unlock(clicon_handle h, char *db); +int clicon_rpc_get2(clicon_handle h, char *xpath, cvec *nsc, netconf_content content, int32_t depth, char *with_defaults, cxobj **xret); int clicon_rpc_get(clicon_handle h, char *xpath, cvec *nsc, netconf_content content, int32_t depth, cxobj **xret); int clicon_rpc_get_pageable_list(clicon_handle h, char *datastore, char *xpath, cvec *nsc, netconf_content content, int32_t depth, diff --git a/lib/src/clixon_proto_client.c b/lib/src/clixon_proto_client.c index da85e1c8..1ffdcf5e 100644 --- a/lib/src/clixon_proto_client.c +++ b/lib/src/clixon_proto_client.c @@ -858,6 +858,21 @@ clicon_rpc_get(clicon_handle h, netconf_content content, int32_t depth, cxobj **xt) +{ + return clicon_rpc_get2(h, xpath, nsc, content, depth, NULL, xt); +} + +/*! Same functionality as the 'clicon_rpc_get' function, but with an additional input parameter 'with-defaults'. + * @see clicon_rpc_get + */ +int +clicon_rpc_get2(clicon_handle h, + char *xpath, + cvec *nsc, /* namespace context for filter */ + netconf_content content, + int32_t depth, + char *with_defaults, + cxobj **xt) { int retval = -1; struct clicon_msg *msg = NULL; @@ -897,6 +912,8 @@ clicon_rpc_get(clicon_handle h, goto done; cprintf(cb, "/>"); } + if (with_defaults != NULL) + cprintf(cb, "%s", with_defaults); cprintf(cb, ""); if ((msg = clicon_msg_encode(session_id, "%s", cbuf_get(cb))) == NULL) diff --git a/test/test_yang_with_defaults.sh b/test/test_yang_with_defaults.sh index fbb94bef..0a20a6da 100755 --- a/test/test_yang_with_defaults.sh +++ b/test/test_yang_with_defaults.sh @@ -14,6 +14,7 @@ APPNAME=example cfg=$dir/conf_yang.xml fyang=$dir/example-default.yang fstate=$dir/state.xml +RESTCONFIG=$(restconf_config none false) cat < $cfg @@ -26,13 +27,16 @@ cat < $cfg /usr/local/lib/$APPNAME/backend example_backend.so$ /usr/local/lib/$APPNAME/netconf - /usr/local/lib/$APPNAME/restconf /usr/local/lib/$APPNAME/cli $APPNAME $dir/$APPNAME.sock /usr/local/var/$APPNAME/$APPNAME.pidfile $dir false + $IETFRFC + clixon-restconf:allow-auth-none + clixon-restconf:fcgi + $RESTCONFIG EOF @@ -155,6 +159,18 @@ if [ $? -ne 0 ]; then err "<${DATASTORE_TOP}>$XML" "$ret" 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 + + new "rfc4243 4.3. Capability Identifier" expecteof "$clixon_netconf -ef $cfg" 0 "$DEFAULTHELLO" \ "urn:ietf:params:netconf:capability:with-defaults:1.0?basic-mode=explicit" @@ -317,6 +333,54 @@ expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" \ " "" +new "rfc8040 4.3. RESTCONF GET" +expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+json' $RCPROTO://localhost/restconf/data/example:interfaces)" \ +0 \ +"HTTP/$HVER 200" \ +"Content-Type: application/yang-data+json" \ +"Cache-Control: no-cache" \ +'{"example:interfaces":{"interface":\[{"name":"eth0","mtu":8192,"status":"ok"},{"name":"eth1","mtu":1500,"status":"ok"},{"name":"eth2","mtu":9000,"status":"not feeling so good"},{"name":"eth3","mtu":1500,"status":"waking up"}\]}}' +expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+xml' $RCPROTO://localhost/restconf/data/example:interfaces)" \ +0 \ +"HTTP/$HVER 200" \ +"Content-Type: application/yang-data+xml" \ +"Cache-Control: no-cache" \ +'eth08192oketh11500oketh29000not feeling so goodeth31500waking up' + +new "rfc8040 B.3.9. RESTCONF with-defaults parameter = report-all" +expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+json' $RCPROTO://localhost/restconf/data/example:interfaces/interface=eth1?with-defaults=report-all)" \ +0 \ +"HTTP/$HVER 200" \ +"Content-Type: application/yang-data+json" \ +"Cache-Control: no-cache" \ +'{"example:interface":\[{"name":"eth1","mtu":1500,"status":"ok"}\]}' +expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+xml' $RCPROTO://localhost/restconf/data/example:interfaces/interface=eth1?with-defaults=report-all)" \ +0 \ +"HTTP/$HVER 200" \ +"Content-Type: application/yang-data+xml" \ +"Cache-Control: no-cache" \ +'eth11500ok' + +new "rfc8040 B.3.9. RESTONF with-defaults parameter = explicit" +expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+json' $RCPROTO://localhost/restconf/data/example:interfaces/interface=eth1?with-defaults=explicit)" \ +0 \ +"HTTP/$HVER 200" \ +"Content-Type: application/yang-data+json" \ +"Cache-Control: no-cache" \ +'{"example:interface":\[{"name":"eth1","status":"ok"}\]}' +expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+xml' $RCPROTO://localhost/restconf/data/example:interfaces/interface=eth1?with-defaults=explicit)" \ +0 \ +"HTTP/$HVER 200" \ +"Content-Type: application/yang-data+xml" \ +"Cache-Control: no-cache" \ +'eth1ok' + + +if [ $RC -ne 0 ]; then + new "Kill restconf daemon" + stop_restconf +fi + if [ $BE -ne 0 ]; then # Bring your own backend new "Kill backend" # Check if premature kill