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

Ladislav Lhotka <ladislav.lhotka@nic.cz> Thu, 27 August 2020 13:09 UTC

Return-Path: <ladislav.lhotka@nic.cz>
X-Original-To: yang-doctors@ietfa.amsl.com
Delivered-To: yang-doctors@ietfa.amsl.com
Received: from localhost (localhost [127.0.0.1]) by ietfa.amsl.com (Postfix) with ESMTP id 0E9B83A0840 for <yang-doctors@ietfa.amsl.com>; Thu, 27 Aug 2020 06:09:43 -0700 (PDT)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -1.897
X-Spam-Level:
X-Spam-Status: No, score=-1.897 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, SPF_HELO_NONE=0.001, SPF_NONE=0.001, URIBL_BLOCKED=0.001] autolearn=ham autolearn_force=no
Received: from mail.ietf.org ([4.31.198.44]) by localhost (ietfa.amsl.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id EsZaVD8QhDQi for <yang-doctors@ietfa.amsl.com>; Thu, 27 Aug 2020 06:09:40 -0700 (PDT)
Received: from trail.lhotka.name (trail.lhotka.name [77.48.224.143]) by ietfa.amsl.com (Postfix) with ESMTP id 6CB743A083E for <yang-doctors@ietf.org>; Thu, 27 Aug 2020 06:09:39 -0700 (PDT)
Received: by trail.lhotka.name (Postfix, from userid 109) id 30D9E8600CA; Thu, 27 Aug 2020 14:57:28 +0200 (CEST)
Received: from localhost (unknown [195.113.220.110]) by trail.lhotka.name (Postfix) with ESMTPSA id 7306786004C; Thu, 27 Aug 2020 14:57:25 +0200 (CEST)
From: Ladislav Lhotka <ladislav.lhotka@nic.cz>
To: Kent Watsen <kent@watsen.net>
Cc: yang-doctors@ietf.org
In-Reply-To: <010001742fecf818-d7acbe40-b835-47a9-a88f-35eb4c8ef9a9-000000@email.amazonses.com>
References: <0100017425c983cb-d9471cc6-34d3-4a49-ab7b-942bca5ae697-000000@email.amazonses.com> <CABCOCHRhE9EqpgKKHpvkCWrmE4JkQN6i5kAF4EMfXF=GA1EVQg@mail.gmail.com> <df41a832-7ebd-9abf-f9e5-d0838797ded0@nic.cz> <CABCOCHS-1XuWGf8U6z=r+WnTh4zH2qfDhbTX2YaPN2fcZt1twg@mail.gmail.com> <06a32179-128a-99f0-b489-56985679964d@nic.cz> <1dab12ae-1f41-10ad-789c-17a38f344efe@nic.cz> <01000174272e7b3e-8c389f49-635c-450a-b74d-6c71a890882d-000000@email.amazonses.com> <87lfi1hnyv.fsf@nic.cz> <010001742fecf818-d7acbe40-b835-47a9-a88f-35eb4c8ef9a9-000000@email.amazonses.com>
Date: Thu, 27 Aug 2020 15:09:34 +0200
Message-ID: <87v9h4w7zl.fsf@nic.cz>
MIME-Version: 1.0
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: quoted-printable
Archived-At: <https://mailarchive.ietf.org/arch/msg/yang-doctors/L5CWMN8fw2POY-ADK6l1Kveh-0s>
Subject: Re: [yang-doctors] Yang syntax for a globally-unique key?
X-BeenThere: yang-doctors@ietf.org
X-Mailman-Version: 2.1.29
Precedence: list
List-Id: Email list of the yang-doctors directorate <yang-doctors.ietf.org>
List-Unsubscribe: <https://www.ietf.org/mailman/options/yang-doctors>, <mailto:yang-doctors-request@ietf.org?subject=unsubscribe>
List-Archive: <https://mailarchive.ietf.org/arch/browse/yang-doctors/>
List-Post: <mailto:yang-doctors@ietf.org>
List-Help: <mailto:yang-doctors-request@ietf.org?subject=help>
List-Subscribe: <https://www.ietf.org/mailman/listinfo/yang-doctors>, <mailto:yang-doctors-request@ietf.org?subject=subscribe>
X-List-Received-Date: Thu, 27 Aug 2020 13:09:43 -0000

Kent Watsen <kent@watsen.net> writes:

>> On Aug 26, 2020, at 3:21 AM, Ladislav Lhotka <ladislav.lhotka@nic.cz> wrote:
>> 
>> Kent Watsen <kent@watsen.net> writes:
>> 
>>> Hi Lada,
>>> 
>>>>>>>     Assume data model:
>>>>>>> 
>>>>>>>       +—rw tenants
>>>>>>>           +—rw tenant [key]
>>>>>>>               +—rw  key        string
>>>>>>>               +—rw admins
>>>>>>>                   +—rw admin [name]
>>>>>>>                        +—rw name     string
>>>>> <snip>
>>>>> 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])";
>>>> 
>>>> Sorry, it should be
>>>> 
>>>>   must "not(preceding-sibling::tenant[admins/admin/name  =
>>>> current()/admins/admin/name])
>>> 
>>> 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.
>
> 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>.

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.

>
> 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.

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

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