ietf-netmod-yang

Only allow unique keys in seperate lists in YANG Model


My yang model has two same-level lists. I need the elements on both lists to be unique. Not unique within each list, but unique in the union of the lists. Is there a way to define this with a must statement or something?

container parent {
    list a {
        key "name";
        leaf name {
            type string;
        }
        leaf something {
            type string;
        }
    }
    list b {
        key "name";
        leaf name {
            type string;
        }
        leaf something-else{
            type string;
        }
    }
}

So, how would I make sure that every element has a different name?


Solution

  • Assuming you need unique values of certain elements within a union between two lists, you can indeed achieve this using a must constraint.

    (Also) assuming that you need unique values for something and something-else, you can put a must constraint on list b with a condition like this:

    not(../a[something=current()/something-else])
    

    So, values of something are not required to be unique across all instances of list a, values of something-else are not required to be unique across all instances of list b, but an intersection across distinct values of something and distinct values of something-else must be an empty set.

    module a {
      yang-version 1.1;
      namespace "a:uri";
      prefix "a";
    
      container parent {
        list a {
            key "name";
            leaf name {
                type string;
            }
            leaf something {
                type string;
            }
        }
        list b {
            must "not(../a[something=current()/something-else])";
            key "name";
            leaf name {
                type string;
            }
            leaf something-else{
                type string;
            }
        }
      }
    }
    

    An example of an invalid document:

    <?xml version="1.0" encoding="utf-8"?>
    <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
      <a1:parent xmlns:a1="a:uri">
        <a1:a>
          <a1:name>a-1</a1:name>
          <a1:something>foo</a1:something>
        </a1:a>
        <a1:a>
          <a1:name>a-2</a1:name>
          <a1:something>foo</a1:something>
        </a1:a>
        <a1:b>
          <a1:name>b-1</a1:name>
          <a1:something-else>bar</a1:something-else> 
        </a1:b>
        <a1:b>
          <a1:name>b-2</a1:name>
          <a1:something-else>foo</a1:something-else>
        </a1:b>
      </a1:parent>
    </data>
    

    Which would fail validation with something like: Error at (16:5): failed assert at "/nc:data/a1:parent/a1:b": Condition "not(../a1:a[a1:something=current()/a1:something-else])" must be true

    Note that this is just one example of how you could approach your requirement. You could, for example, move my condition to the something-else leaf, which would then become something like this (did not test):

    not(.=../../a/something)