]> git.puffer.fish Git - mirror/frr.git/commitdiff
lib: fix specific entry queries 15073/head
authorChristian Hopps <chopps@labn.net>
Mon, 1 Jan 2024 09:04:19 +0000 (09:04 +0000)
committerChristian Hopps <chopps@labn.net>
Tue, 2 Jan 2024 09:47:15 +0000 (09:47 +0000)
- fix key leaf queries
- fix specific list entry with non-key leaf top element

Signed-off-by: Christian Hopps <chopps@labn.net>
lib/northbound_oper.c
tests/topotests/mgmt_oper/simple-results/result-intf-eth0-name.json [new file with mode: 0644]
tests/topotests/mgmt_oper/simple-results/result-intf-eth0-vrf.json [new file with mode: 0644]
tests/topotests/mgmt_oper/simple-results/result-intf-name.json [new file with mode: 0644]
tests/topotests/mgmt_oper/test_simple.py

index 4a7a0bb559b7eefddca4cb3ea33a44ba810a6366..ab9abdeae2ee7e04674591a172f4e35b2809b672 100644 (file)
@@ -499,7 +499,11 @@ static enum nb_error nb_op_ys_init_node_infos(struct nb_op_yield_state *ys)
                        ret = NB_ERR_NOT_FOUND;
                return ret;
        }
-       assert(CHECK_FLAG(node->schema->nodetype, LYS_CONTAINER | LYS_LIST));
+       while (node &&
+              !CHECK_FLAG(node->schema->nodetype, LYS_CONTAINER | LYS_LIST))
+               node = &node->parent->node;
+       if (!node)
+               return NB_ERR_NOT_FOUND;
 
        inner = (struct lyd_node_inner *)node;
        for (len = 1; inner->parent; len++)
@@ -1237,9 +1241,18 @@ static enum nb_error __walk(struct nb_op_yield_state *ys, bool is_resume)
                         * `route-entry` element for a query
                         * `.../route-entry/metric` where the list element had
                         * no metric value.
+                        *
+                        * However, if the user query is for a key of a list
+                        * element, then when we reach that list element it will
+                        * have no non-key children, check for this condition
+                        * and do not reap if true.
                         */
                        if (!list_start && ni->inner &&
                            !lyd_child_no_keys(&ni->inner->node) &&
+                           /* not the top element with a key match */
+                           !((darr_ilen(ys->node_infos) ==
+                              darr_ilen(ys->schema_path) - 1) &&
+                             lysc_is_key((*darr_last(ys->schema_path)))) &&
                            /* is this at or below the base? */
                            darr_ilen(ys->node_infos) <= ys->query_base_level)
                                lyd_free_tree(&ni->inner->node);
@@ -1674,7 +1687,6 @@ static enum nb_error nb_op_walk_start(struct nb_op_yield_state *ys)
         * Get the node_info path (stack) corresponding to the uniquely
         * resolvable data nodes from the beginning of the xpath query.
         */
-       // I think this moves
        ret = nb_op_ys_init_node_infos(ys);
        if (ret != NB_OK)
                return ret;
diff --git a/tests/topotests/mgmt_oper/simple-results/result-intf-eth0-name.json b/tests/topotests/mgmt_oper/simple-results/result-intf-eth0-name.json
new file mode 100644 (file)
index 0000000..3988204
--- /dev/null
@@ -0,0 +1,9 @@
+{
+  "frr-interface:lib": {
+    "interface": [
+      {
+        "name": "r1-eth0"
+      }
+    ]
+  }
+}
diff --git a/tests/topotests/mgmt_oper/simple-results/result-intf-eth0-vrf.json b/tests/topotests/mgmt_oper/simple-results/result-intf-eth0-vrf.json
new file mode 100644 (file)
index 0000000..3a6eeb8
--- /dev/null
@@ -0,0 +1,10 @@
+{
+  "frr-interface:lib": {
+    "interface": [
+      {
+        "name": "r1-eth0",
+        "vrf": "default"
+      }
+    ]
+  }
+}
diff --git a/tests/topotests/mgmt_oper/simple-results/result-intf-name.json b/tests/topotests/mgmt_oper/simple-results/result-intf-name.json
new file mode 100644 (file)
index 0000000..9d8ea75
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "frr-interface:lib": {
+    "interface": [
+      {
+        "name": "lo"
+      },
+      {
+        "name": "r1-eth0"
+      },
+      {
+        "name": "lo-red"
+      },
+      {
+        "name": "r1-eth1"
+      },
+      {
+        "name": "red"
+      }
+    ]
+  }
+}
index f3d64e156a3d300c120c8033a0dbec0194998a19..1f9f21b8defba3af75d0c243f55426e442bb17bc 100644 (file)
@@ -46,6 +46,23 @@ def test_oper_simple(tgen):
         pytest.skip(tgen.errors)
 
     query_results = [
+        (
+            # Non-key query with key specific selection
+            '/frr-interface:lib/interface[name="r1-eth0"]/vrf',
+            "simple-results/result-intf-eth0-vrf.json",
+        ),
+        # Test machines will have different sets of interfaces so the test results will
+        # vary and need to be generated dynamically before this test is re-enabled
+        # (
+        #     # Key query on generic list
+        #     "/frr-interface:lib/interface/name",
+        #     "simple-results/result-intf-name.json",
+        # ),
+        (
+            # Key query with key specific selection
+            '/frr-interface:lib/interface[name="r1-eth0"]/name',
+            "simple-results/result-intf-eth0-name.json",
+        ),
         ("/frr-vrf:lib", "simple-results/result-lib.json"),
         ("/frr-vrf:lib/vrf", "simple-results/result-lib-vrf-nokey.json"),
         (