Must constraint

Here is my yang.

container server {
  leaf-list interfaces {
	type leafref {
      path "/if:interfaces/if:interface/if:name";
    }
  }
}

container client {
  list client-if {
	key ifName;
    leaf ifName {
	  type string;
	}
	
	leaf enable {
	  type boolean;
	  default "false";
	}
  }
}

Constraint for the server leaf-list element should be such that if the client is enabled on the same interface, there should be an error thrown.
So I added a must statement as below.

tailf:annotate "/server/interfaces" {
  must "(not /client/client-if[ifName=current()]/enable) or " +
   "(/client/client-if[ifName=current()]/enable = 'false')" {
    tailf:dependency "/client/client-if/enable";
    error-message "Client has to be disabled to enable server on this interface.";
  }
}

This does not work. It is not throwing error when client is enabled on the same interface on which I am trying to enable server too.
Can some one tell me what am I making wrong here?

I am suspecting that you may not have compiled your annotated YANG module as it works just fine for me with your must statements. However, it is important to note that this kind of dependencies is not a recommended practice. There shouldn’t be any built-in knowledge of having some interface to be disabled first before some other container can be configured in your YANG model. As this will create unnecessary complexity to automate the provisioning of your device from your orchestrating software.

Following is the terminal output when I ran it as a full example:

$ cat test.yang test-ann.yang
module test {

  namespace "http://tail-f.com/ns/example/test";
  prefix te;

  import ietf-interfaces {
    prefix if;
  }

  import tailf-common {
    prefix tailf;
  }

  container server {
    leaf-list interfaces {
      type leafref {
          path "/if:interfaces/if:interface/if:name";
      }
    }
  }
  
  container client {
    list client-if {
      key ifName;
      leaf ifName {
  	  type string;
      }
  	
      leaf enable {
        type boolean;
        default "false";
      }
    }
  }

}

module test-ann {

  namespace "http://tail-f.com/ns/example/test-ann";
  prefix tea;

  import test {
    prefix te;
  }

  import tailf-common {
    prefix tailf;
  }

  tailf:annotate "/te:server/te:interfaces" {
    must "(not /client/client-if[ifName=current()]/enable) or " +
      "(/client/client-if[ifName=current()]/enable = 'false')" {
      tailf:dependency "/client/client-if/enable";
      error-message "Client has to be disabled to enable server on this interface.";
    }
  }
}

$ make clean all
rm -rf \
		*.o *.a *.xso *.fxs *.xsd *.ccl \
		*_proto.h \
		./confd-cdb *.db aaa_cdb.* \
		rollback*/rollback{0..999} rollback{0..999} \
		host.key host.cert ssh-keydir \
		*.log confderr.log.* \
		etc *.access \
		running.invalid global.data _tmp*
rm -rf test.fxs ietf-interfaces.fxs iana-if-type.fxs 2> /dev/null || true
confdc -c -a test-ann.yang test.yang
test-ann.yang:18: warning: Given dependencies are not equal to calculated: ., ./:not/:client/:client-if/:enable, ./:not/:client/:client-if/:ifName, /client/:client-if/:enable, /client/:client-if/:ifName. Consider removing tailf:dependency statements.
confdc --fail-on-warnings  -c -o ietf-interfaces.fxs  ietf-interfaces.yang
confdc --fail-on-warnings  -c -o iana-if-type.fxs  iana-if-type.yang
mkdir -p ./confd-cdb
cp $CONFD_DIR/var/confd/cdb/aaa_init.xml ./confd-cdb
ln -s $CONFD_DIR/etc/confd/ssh ssh-keydir
Build complete
$ make start
### Killing any confd daemon
confd --stop    || true
confd -c confd.conf --addloadpath $CONFD_DIR/etc/confd 
$ make cli-c
confd_cli -C --user=admin --groups=admin \
		--interactive  || echo Exit

admin connected from 127.0.0.1 using console on localhost
localhost# config 
Entering configuration mode terminal
localhost(config)# interfaces interface 
Possible completions:
  <name:string>  range
localhost(config)# interfaces interface if0 type atm
localhost(config-interface-if0)# exit
localhost(config)# client client-if 
Possible completions:
  <ifName:string>  range
localhost(config)# client client-if if0 enable true
localhost(config-client-if-if0)# exit
localhost(config)# server interfaces if0 
localhost(config)# validate
Failed: 'server interfaces' (value "if0"): Client has to be disabled to enable server on this interface.

The above line should have been written as follows:

    must "(not (/client/client-if[ifName=current()]/enable)) or " +

One way to verify your must statements is to turn on XPath tracing in confd.conf as follows:

/confdConfig/logs/xpathTraceLog/enabled (xs:boolean) [false]
enabled is either "true" or "false". If "true", all XPath execution is logged.

/confdConfig/logs/xpathTraceLog/filename (xs:string)
The name of the file where the XPath trace log is written.

Another way is to turn on devtools as described on page 268 of the ConfD 6.2 User Guide and use the xpath command as described on page 291 of the ConfD 6.2 User Guide to evaluate your must statements dynamically.

Working through examples.confd/validate/xpath_must is a good starting point for learning how to work with must statements.