Subject: [yang-doctors] usage of mandatory node in an optional choice

From: Andy Bierman <[email-masked]>
Date: Thu, 25 Jan 2018 14:21:17 -0800

Hi,

I am working on a bug in our server, and I noticed the NACM rule choice
is a bit odd -- why is leaf path within implied case "path" a mandatory
node?
Why does this node have mandatory=true and none of the other leafs have
that?

Is this 'path' leaf really mandatory, given that the choice is optional?
Perhaps this is future-proofing -- making sure if the case is augmented
that the path node is still provided?  (If so, then why not do all
short-case
definitions this way?)

IMO this usage of mandatory true should be avoided, or clarified, or both...

Andy

        choice rule-type {
            description
              "This choice matches if all leafs present in the rule
             match the request.  If no leafs are present, the
             choice matches all requests.";
            leaf rpc-name {
              type union {
                type matchall-string-type
<http://www.netconfcentral.org/modulereport/ietf-netconf-acm#matchall-string-type.109>;
                type string;
              }
              description
                "This leaf matches if it has the value '*' or if
                 its value equals the requested protocol operation
                 name.";
            }
            leaf notification-name {
              type union {
                type matchall-string-type
<http://www.netconfcentral.org/modulereport/ietf-netconf-acm#matchall-string-type.109>;
                type string;
              }
              description
                "This leaf matches if it has the value '*' or if its
                 value equals the requested notification name.";
            }
            leaf path {
              type node-instance-identifier
<http://www.netconfcentral.org/modulereport/ietf-netconf-acm#node-instance-identifier.175>;
              mandatory true;
              description
                "Data Node Instance Identifier associated with the
                 data node, action, or notification controlled by
                 this rule.

                 Configuration data or state data instance
                 identifiers start with a top-level data node.  A
                 complete instance identifier is required for this
                 type of path value.

                 The special value '/' refers to all possible
                 datastore contents.";
            }
          }  // choice rule-type

---

From: Martin Bjorklund <[email-masked]>
Date: Fri, 26 Jan 2018 09:22:28 +0100 (CET)

Hi,

> Why does this node have mandatory=true and none of the other leafs have

Browsing through the history of this module I found this design from
2010:

    list data-rule {
        key "rule-name";
        ordered-by user;

        ...

        leaf path {
          type schema-instance-identifier;
          mandatory true;
    ...

So I think this is merely a left over from this design that we forgot
to change.

> that the path node is still provided?  (If so, then why not do all

Future-proofing is an interesting angle.  Maybe we should use *more*
mandatory true in cases (!) like this...?

/martin

---

From: Christian Hopps <[email-masked]>
Date: Fri, 26 Jan 2018 06:36:38 -0500

...
> mandatory true in cases (!) like this...?

So I recently used a choice, and wondered why the "case" name values were not
included explicitly in the tree and instead the case choice was simply implied
by one of it's leaf nodes being present from underneath the case. It struck me
as an overly clever optimization. This seems to bear that feeling out.

If one has a choice with case nodes that are non-mandatory, it would
seem that yang would allow augments to these cases to exclusively select those
cases and it might seem that these augments are backward compatible
when in fact they are not:

  module foo;
  choice X {
    case A {
      leaf a {
        type boolean;
      }
    }
    case B {
      leaf b {
        type boolean;
      }
    }
  }

  module bar;
  augment /foo:X/foo:B/ {
    leaf bb {
      type string;
    }
  }

Now a client that only implements module foo might receive:

    <bar:bb>extra-info</bar:bb>

and have no idea that case B of choice X had been chosen.

So for choices to allow for augmenting with backward compatibility each case must
have at least one mandatory leaf in it. To my earlier point, this wouldn't have
been required if the case name itself had been included in the returned tree.

Thanks,
Chris.