Subject: [yang-doctors] Yang syntax for a globally-unique key?

From: Kent Watsen <[email-masked]>
Date: Tue, 25 Aug 2020 13:23:17 +0000

[trying here before the “netmod” list]

YANG Doctors,

Assume data model:

  +—rw tenants
      +—rw tenant [key]
          +—rw  key        string
          +—rw admins
              +—rw admin [name]
                   +—rw name     string

The "admin" list’s key “name” ensures that the names are unique per tenant, but not globally.   Is it possible to place a “must” statement on the “tenants” container to ensure globally-unique admin names?

Can anyone offer syntax to do so?

Kent

---

From: Christian Hopps <[email-masked]>
Date: Tue, 25 Aug 2020 10:48:48 -0400

Could you create a root level global list of admins and then leaf-ref them under tenants?

Thanks,
Chris.

> On Aug 25, 2020, at 9:23 AM, Kent Watsen <[email-masked]> wrote:
> 
> _______________________________________________
> yang-doctors mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/yang-doctors

---

From: Andy Bierman <[email-masked]>
Date: Tue, 25 Aug 2020 08:08:04 -0700

On Tue, Aug 25, 2020 at 6:23 AM Kent Watsen <[email-masked]> wrote:

> The "admin" list’s key “name” ensures that the names are unique per
> tenant, but not globally.   Is it possible to place a “must” statement on
> the “tenants” container to ensure globally-unique admin names?
>
Isn't this a use-case for unique-stmt?

   list tenant {
       unique "admins/admin/name";
       ...
   }

> Kent

Andy

---

From: "Reshad Rahman (rrahman)" <[email-masked]>
Date: Tue, 25 Aug 2020 15:22:01 +0000

I don’t think unique-stmt works for this case, see https://github.com/netmod-wg/yang-next/issues/74

Regards,
Reshad.

From: yang-doctors <[email-masked]> on behalf of 'Andy Bierman' <[email-masked]>
Date: Tuesday, August 25, 2020 at 11:08 AM
To: Kent Watsen <[email-masked]>
Cc: YANG Doctors <[email-masked]>
Subject: Re: [yang-doctors] Yang syntax for a globally-unique key?

On Tue, Aug 25, 2020 at 6:23 AM Kent Watsen <[email-masked]<mailto:[email-masked]>> wrote:
[trying here before the “netmod” list]

YANG Doctors,

Assume data model:

  +—rw tenants
      +—rw tenant [key]
          +—rw  key        string
          +—rw admins
              +—rw admin [name]
                   +—rw name     string

   list tenant {

Kent

Andy

_______________________________________________
yang-doctors mailing list
[email-masked]<mailto:[email-masked]>
https://www.ietf.org/mailman/listinfo/yang-doctors

---

From: Kent Watsen <[email-masked]>
Date: Tue, 25 Aug 2020 15:55:13 +0000

Unique did not work with `yanglint`:

	err : Unique argument references list.

This MAY be a bug in yanglint.  Hard to say from that GitHub issue if this syntax is supposed to work or not.

Lada writes that a “must” statement could be used when a “unique” statement fails.  What might that “must” statement look like?

Kent

> On Aug 25, 2020, at 11:22 AM, Reshad Rahman (rrahman) <rrahman=[email-masked]> wrote:
> 
> I don’t think unique-stmt works for this case, see https://github.com/netmod-wg/yang-next/issues/74 <https://github.com/netmod-wg/yang-next/issues/74>
>  
> Regards,
> Reshad.
>  
> From: yang-doctors <[email-masked] <mailto:[email-masked]>> on behalf of 'Andy Bierman' <[email-masked] <mailto:[email-masked]>>
> To: Kent Watsen <[email-masked] <mailto:[email-masked]>>
> Cc: YANG Doctors <[email-masked] <mailto:[email-masked]>>
> On Tue, Aug 25, 2020 at 6:23 AM Kent Watsen <[email-masked] <mailto:[email-masked]>> wrote:
>> [email-masked] <mailto:[email-masked]>
>> https://www.ietf.org/mailman/listinfo/yang-doctors <https://www.ietf.org/mailman/listinfo/yang-doctors>_______________________________________________
> [email-masked] <mailto:[email-masked]>
> https://www.ietf.org/mailman/listinfo/yang-doctors <https://www.ietf.org/mailman/listinfo/yang-doctors>

---

From: Ladislav Lhotka <[email-masked]>
Date: Tue, 25 Aug 2020 19:06:14 +0200

On 25. 08. 20 17:08, Andy Bierman wrote:
>     tenant, but not globally.   Is it possible to place a “must”
>     statement on the “tenants” container to ensure globally-unique admin
>     names?
> 

I am surprised it is you who is proposing this. :-)

https://mailarchive.ietf.org/arch/msg/netmod/MYq9CT7BKuKBp63urg-q6-GP7mM/

Lada

-- 
Ladislav Lhotka
Head, CZ.NIC Labs
PGP Key ID: 0xB8F92B08A9F76C67

---

From: Andy Bierman <[email-masked]>
Date: Tue, 25 Aug 2020 10:14:47 -0700

> https://mailarchive.ietf.org/arch/msg/netmod/MYq9CT7BKuKBp63urg-q6-GP7mM/

This is a separate issue about intentionally augmenting a target with
multiple siblings with the same local-name.  This is not CLI friendly
(and that mattered a lot more in 2012 than it does now)

Andy

---

From: Ladislav Lhotka <[email-masked]>
Date: Tue, 25 Aug 2020 19:36:37 +0200

On 25. 08. 20 19:14, Andy Bierman wrote:
> 
> 
> On Tue, Aug 25, 2020 at 10:06 AM Ladislav Lhotka <[email-masked]
> <mailto:[email-masked]>> wrote:
> 
> 
> 
>     > On Tue, Aug 25, 2020 at 6:23 AM Kent Watsen <[email-masked]
>     <mailto:[email-masked]>
>     > <mailto:[email-masked] <mailto:[email-masked]>>> wrote:
>     >

> (and that mattered a lot more in 2012 than it does now)

I don't see any augmentation involved in either case. Anyway, I do agree
that the unique statement should work. Otherwise, section 12.16 of RFC
6110 essentially gives what Kent asks for, which is in this case:

    must "not(preceding-sibling::tenant[current()/admins/admin/name])";

Lada

>     <mailto:[email-masked] <mailto:[email-masked]>>

---

From: Ladislav Lhotka <[email-masked]>
Date: Tue, 25 Aug 2020 19:39:33 +0200

>     must "not(preceding-sibling::tenant[current()/admins/admin/name])";

Sorry, it should be

    must "not(preceding-sibling::tenant[admins/admin/name  =
current()/admins/admin/name])

Lada

---

From: Kent Watsen <[email-masked]>
Date: Tue, 25 Aug 2020 19:53:11 +0000

Hi Lada,

>> <snip>

I thought "preceding-sibling” was for selecting a sibling?  In my example, “tenant” doesn’t have a sibling, so what is selected?  You *are* putting the must  statement on the “tenant” node, right?

> Lada

K.

---

From: Ladislav Lhotka <[email-masked]>
Date: Wed, 26 Aug 2020 09:21:12 +0200

> I thought "preceding-sibling” was for selecting a sibling?  In my example, “tenant” doesn’t have a sibling, so what is selected?  You *are* putting the must  statement on the “tenant” node, right?

Yes. In your example, "tenant" is a list, and its instances/entries are sibling nodes in the XPath data model. So the rule states that there must not be two "tenant" entries containing admins/admin/leaf with the same value. If this condition is violated, it is reported for the second "tenant" entry.

The same rule can be written in other ways, too, but the advantage of preceding-sibling:: is that the check is performed only "above the diagonal" of all pairwise combinations of "tenant" entries.

Lada

---

From: Kent Watsen <[email-masked]>
Date: Thu, 27 Aug 2020 12:38:13 +0000

> On Aug 26, 2020, at 3:21 AM, Ladislav Lhotka <[email-masked]> wrote:
> 

I see, that makes sense now.  I didn’t realize that "preceding-sibling” selected all siblings.

Pyang validated the corrected expression above, but yanglint threw an error, as described by: https://github.com/CESNET/libyang/issues/1180 <https://github.com/CESNET/libyang/issues/1180>.

I have not yet tested with Yangson.  Is it known if Yangson supports "preceding-sibling”?  Looking at https://yangson.labs.nic.cz/xpath.html <https://yangson.labs.nic.cz/xpath.html> I see this:

    NotSupported – if the input XPath expression contains a feature that
    isn’t supported by the implementation, such as the preceding:: axis.

Kent

---

From: Ladislav Lhotka <[email-masked]>
Date: Thu, 27 Aug 2020 15:09:34 +0200

> Pyang validated the corrected expression above, but yanglint threw an error, as described by: https://github.com/CESNET/libyang/issues/1180 <https://github.com/CESNET/libyang/issues/1180>.

Yes, we discussed this with Michal previously. The fact that there is no specific prescribed order doesn't mean there is no order at all. XPath data model expects the siglings to be in a sequence.

>     isn’t supported by the implementation, such as the preceding:: axis.

Yangson does support it, see below. Of course, preceding:: axis really makes no sense with YANG-modelled data.

Lada

(yangson) $ cat test.yang 
module test {
  yang-version 1.1;
  namespace "https://example.net/test";
  prefix "t";

  container tenants {
    list tenant {
      key key;
      must "not(preceding-sibling::tenant[admins/admin/name = current()/admins/admin/name])";
      leaf key {
        type string;
      }
      container admins {
        list admin {
          key name;
          leaf name {
            type string;
          }
        }
      }
    }
  }
}

(yangson) $ cat ylib.json 
{
  "ietf-yang-library:modules-state": {
    "module-set-id": "",
    "module": [
      {
        "name": "test",
        "revision": "",
        "namespace": "https://example.net/test",
        "conformance-type": "implement"
      }
    ]
  }
}
(yangson) $ cat inst1.json 
{
    "test:tenants": {
	"tenant": [
	    {
		"key": "foo",
		"admins": {
		    "admin": [ { "name": "alice" } ]
		}
	    },
	    {
		"key": "bar",
		"admins": {
		    "admin": [ { "name": "bob" } ]
		}
	    }
        ]
    }
}

(yangson) $ cat inst2.json 
{
    "test:tenants": {
	"tenant": [
	    {
		"key": "foo",
		"admins": {
		    "admin": [ { "name": "alice" } ]
		}
	    },
	    {
		"key": "bar",
		"admins": {
		    "admin": [ { "name": "alice" } ]
		}
	    }
        ]
    }
}

(yangson) $ yangson -v inst1.json ylib.json 
(yangson) $ yangson -v inst2.json ylib.json 
Semantic error: [/test:tenants/tenant/1] must-violation

---

From: Kent Watsen <[email-masked]>
Date: Thu, 27 Aug 2020 13:44:46 +0000

> Yes, we discussed this with Michal previously. The fact that there is no specific prescribed order doesn't mean there is no order at all. XPath data model expects the siglings to be in a sequence.

Michael says that he’ll schedule it for near end-of-year, in yanglint 2.0 only.

> Yangson does support it, see below. Of course, preceding:: axis really makes no sense with YANG-modelled data.

Oh, happy days  :)

To workaround the yanglint issue, I guess that code can dynamically add a new “must” expression to an instance of Yangson’s “SchemaNode” class here: https://yangson.labs.nic.cz/schemanode.html#yangson.schemanode.SchemaNode.must <https://yangson.labs.nic.cz/schemanode.html#yangson.schemanode.SchemaNode.must>.

K.