yanglint FEATURE schema mount support (#1901)
* modify existing context if provided
In ly_ctx_new_yldata(), check if *ctx is NULL. If so, proceed as before
with allocating a new context. Otherwise, load modules into the existing
context.
Signed-off-by: Eric Kinzie <ekinzie@labn.net>
* add parent-reference xpath helper to schema-mount plugin
This new function produces a list of schema nodes from the expanded
parent-reference xpath expressions.
Signed-off-by: Eric Kinzie <ekinzie@labn.net>
* add context lookup to schema-mount plugin
This function allocates a new context for a particular instance of the
yangmnt:mount-point extension.
Signed-off-by: Eric Kinzie <ekinzie@labn.net>
* yanglint: schema-mount extension callback
Add a commandline argument "-x" that accepts a file containing extension
data, used to create a context for the schema-mount extension. This file
has the same format as what is provided to the "-Y" option. A callback
function for the schema-mount extenion is registered if the new option
is specified.
This allows validating instance data for models that include a schema
mount point.
Signed-off-by: Eric Kinzie <ekinzie@labn.net>
* yanglint: print mounted schema trees
Display "mp" flag for mount point and print mounted tree. Also display
the / and @ opts in node names.
Signed-off-by: Eric Kinzie <ekinzie@labn.net>
* add unit test for tree mount-point flag
Test is courtesy of aPiecek <piecek@cesnet.cz>.
Signed-off-by: Eric Kinzie <ekinzie@labn.net>
* add example data files for validation with schema-mount
From tools/lint/examples directory:
% ../../../build/yanglint \
-f json -t config -p ../../../models -p . \
-Y ./sm-context-main.xml -x ./sm-context-extension.xml sm-data.xml
% ../../../build/yanglint \
-f tree -p ../../../models -p . \
-Y ./sm-context-main.xml -x ./sm-context-extension.xml sm-main.yang
Signed-off-by: Eric Kinzie <ekinzie@labn.net>
Signed-off-by: Eric Kinzie <ekinzie@labn.net>
Co-authored-by: Eric Kinzie <ekinzie@labn.net>
diff --git a/src/plugins_exts/schema_mount.c b/src/plugins_exts/schema_mount.c
index 7aed9a9..8661894 100644
--- a/src/plugins_exts/schema_mount.c
+++ b/src/plugins_exts/schema_mount.c
@@ -351,7 +351,7 @@
struct lyplg_ext_sm *sm_data = ext->data;
LY_ERR ret = LY_SUCCESS, r;
struct lyd_node *node = NULL;
- struct ly_ctx *new_ctx;
+ struct ly_ctx *new_ctx = NULL;
uint32_t i;
const char *content_id = NULL;
void *mem;
@@ -442,7 +442,7 @@
{
struct lyplg_ext_sm *sm_data = ext->data;
LY_ERR r;
- struct ly_ctx *new_ctx;
+ struct ly_ctx *new_ctx = NULL;
uint32_t i;
void *mem;
@@ -538,7 +538,7 @@
{
LY_ERR r;
const struct lys_module *mod;
- const struct ly_ctx *ext_ctx;
+ const struct ly_ctx *ext_ctx = NULL;
/* get context based on ietf-yang-library data */
if ((r = schema_mount_get_ctx(ext, &ext_ctx))) {
@@ -556,6 +556,27 @@
return *snode ? LY_SUCCESS : LY_ENOT;
}
+static LY_ERR
+schema_mount_get_parent_ref(const struct lysc_ext_instance *ext, const struct lyd_node *ext_data,
+ struct ly_set **set)
+{
+ LY_ERR ret = LY_SUCCESS;
+ char *path = NULL;
+
+ /* get all parent references of this mount point */
+ if (asprintf(&path, "/ietf-yang-schema-mount:schema-mounts/mount-point[module='%s'][label='%s']"
+ "/shared-schema/parent-reference", ext->module->name, ext->argument) == -1) {
+ EXT_LOGERR_MEM_GOTO(ext, ret, cleanup);
+ }
+ if ((ret = lyd_find_xpath(ext_data, path, set))) {
+ goto cleanup;
+ }
+
+cleanup:
+ free(path);
+ return ret;
+}
+
/**
* @brief Duplicate all accessible parent references for a shared-schema mount point.
*
@@ -587,12 +608,7 @@
goto cleanup;
}
- /* get all parent references of this mount point */
- if (asprintf(&path, "/ietf-yang-schema-mount:schema-mounts/mount-point[module='%s'][label='%s']"
- "/shared-schema/parent-reference", ext->module->name, ext->argument) == -1) {
- EXT_LOGERR_MEM_GOTO(ext, ret, cleanup);
- }
- if ((ret = lyd_find_xpath(ext_data, path, &set))) {
+ if ((ret = schema_mount_get_parent_ref(ext, ext_data, &set))) {
goto cleanup;
}
@@ -671,6 +687,61 @@
return ret;
}
+LY_ERR
+lyplg_ext_schema_mount_get_parent_ref(const struct lysc_ext_instance *ext, struct ly_set **refs)
+{
+ LY_ERR res;
+ struct ly_set *pref_set = NULL;
+ struct ly_set *snode_set;
+ struct ly_set *results_set = NULL;
+ struct lyd_node *ext_data;
+ ly_bool ext_data_free;
+
+ /* get operational data with ietf-yang-library and ietf-yang-schema-mount data */
+ if ((res = lyplg_ext_get_data(ext->module->ctx, ext, (void **)&ext_data, &ext_data_free))) {
+ return res;
+ }
+
+ LY_CHECK_GOTO(res = schema_mount_get_parent_ref(ext, ext_data, &pref_set), out);
+ if (pref_set->count == 0) {
+ goto out;
+ }
+
+ LY_CHECK_GOTO(res = ly_set_new(&results_set), out);
+
+ for (uint32_t i = 0; i < pref_set->count; ++i) {
+ struct lyd_node_term *term;
+ struct lyd_value_xpath10 *xp_val;
+ char *value;
+ struct ly_err_item *err;
+
+ term = (struct lyd_node_term *)pref_set->dnodes[i];
+ LYD_VALUE_GET(&term->value, xp_val);
+ LY_CHECK_GOTO(res = lyplg_type_print_xpath10_value(xp_val, LY_VALUE_JSON, NULL, &value, &err), out);
+ LY_CHECK_ERR_GOTO(res = lys_find_xpath(ext->module->ctx, NULL, value, 0, &snode_set), free(value), out);
+ free(value);
+ for (uint32_t sn = 0; sn < snode_set->count; sn++) {
+ struct lysc_node *snode = snode_set->snodes[sn];
+
+ if ((res = ly_set_add(results_set, snode, 0, NULL))) {
+ ly_set_free(snode_set, NULL);
+ ly_set_free(results_set, NULL);
+ goto out;
+ }
+ }
+ ly_set_free(snode_set, NULL);
+ }
+
+ *refs = results_set;
+
+out:
+ if (ext_data_free) {
+ lyd_free_all(ext_data);
+ }
+ ly_set_free(pref_set, NULL);
+ return res;
+}
+
/**
* @brief Validate callback for schema mount.
*/
@@ -836,6 +907,43 @@
free(sm_data);
}
+LIBYANG_API_DEF LY_ERR
+lyplg_ext_schema_mount_create_context(const struct lysc_ext_instance *ext, struct ly_ctx **ctx)
+{
+ struct lyd_node *ext_data;
+ ly_bool ext_data_free;
+ ly_bool config;
+ ly_bool shared;
+ LY_ERR res;
+
+ if (!ext->module->ctx->ext_clb) {
+ return LY_EINVAL;
+ }
+
+ if (strcmp(ext->def->module->name, "ietf-yang-schema-mount") ||
+ strcmp(ext->def->name, "mount-point")) {
+ return LY_EINVAL;
+ }
+
+ /* get operational data with ietf-yang-library and ietf-yang-schema-mount data */
+ if ((res = lyplg_ext_get_data(ext->module->ctx, ext, (void **)&ext_data, &ext_data_free))) {
+ return res;
+ }
+
+ /* learn about this mount point */
+ if ((res = schema_mount_get_smount(ext, ext_data, &config, &shared))) {
+ goto out;
+ }
+
+ res = schema_mount_create_ctx(ext, ext_data, config, ctx);
+
+out:
+ if (ext_data_free) {
+ lyd_free_all(ext_data);
+ }
+ return res;
+}
+
/**
* @brief Plugin descriptions for the Yang Schema Mount extension.
*