Skip to content

/czechlight-system:journal-upload as a presence container is a bit confusing #19

Description

@jktjkt

I was trying to reproduce CESNET/netconf-cli#20, and I ended up here. We have this YANG model:

module: czechlight-system
  ...
  +--rw journal-upload!
     +--rw protocol?   enumeration
     +--rw host        inet:host
     +--rw port?       inet:port-number

...which means that /czechlight-system:journal-upload is a presence container with a mandatory leaf host. The problem is that the CLI happily creates presence containers when creating a leaf below them, but it won't delete an empty presence container implicitly (which is a sane behavior).

Here's how it works:

Connected to sysrepo [datastore target: operational]
/> get czechlight-system:journal-upload
/> set czechlight-system:journal-upload/host "127.0.0.1"
/> commit 
/> delete czechlight-system:journal-upload/host
/> commit 
[ERR] Mandatory node "host" instance does not exist. (path "/czechlight-system:journal-upload")
The following errors occured:
 Message: Mandatory node "host" instance does not exist. (path "/czechlight-system:journal-upload")
/> get czechlight-system:journal-upload
/czechlight-system:journal-upload = (presence container)
/czechlight-system:journal-upload/protocol = https
/czechlight-system:journal-upload/host = 127.0.0.1
/czechlight-system:journal-upload/port = 19532

I guess that the reason for having a presence container and some leaves below has something to do with default values, and that with this model the user only has to provide the hostname while the protocol and port are defaulted. Also, we identified a possible problem with ietf-inet-types:uri during review because we cannot allow newlines in env vars for systemd, which is why we ended up with three leafs.

Since there's no error-message for the mandatory statement, and since I already wated at least five minutes on this one, I was wondering if there's some way of making the UX a bit nicer. I ended up with this:

module foo {
  namespace foo;
  prefix foo;
  container foo {
    presence true;
    must "count(x) = 1" {
      error-message "Leaf `x` is not set, remove the entire container `/foo:foo` if you do not need it.";
    }
    leaf x {
      type string;
      mandatory true;
    }
  }
}
{
  "foo:foo": {
  }
}
$ yanglint -t config foo.json foo.yang 
libyang err : Leaf `x` is not set, remove the entire container `/foo:foo` if you do not need it. (/foo:foo)
libyang err : Mandatory node "x" instance does not exist. (/foo:foo)
YANGLINT[E]: Failed to parse input data file "foo.json".

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions