# Wildcard card in a xpath of must constraint

**URL:** <https://dmap-community.ductus.global/t/wildcard-card-in-a-xpath-of-must-constraint/3097>\
**Category:** YANG\
**Created:** [June 11, 2020, 5:07am UTC](https://dmap-community.ductus.global/t/wildcard-card-in-a-xpath-of-must-constraint/3097 "2020-06-11T05:07:48Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![nandakm](https://avatars.discourse-cdn.com/v4/letter/n/c0e974/32.png) [@nandakm](https://dmap-community.ductus.global/u/nandakm)\
**Post date:** [June 11, 2020, 5:07am UTC](https://dmap-community.ductus.global/t/wildcard-card-in-a-xpath-of-must-constraint/3097/1 "2020-06-11T05:07:48Z")

</div>

hi

I have a node, which needs to check if someone else has a reference  
when its deleted , .

Basically i want to check if a node under a list is set .  
can i wildcard the xpath for the list name so that it checks all the list items if it contains a certain leaf set ?

e.g if i have configs like  
listname A leaf “bgp100”  
listname B Leaf “bgp200”  
listname C Leaf “bgp100”  
listname D leaf “bgp100”

and i have config like  
“no bgp100”  
i would like to check before deleting the node bgp100, i want to check if any of the listA B or C is using the bgp100.

My constraint is , I cannot use leafref as the creation of  
list A leaf “bgp100” is not really dependent on the bgp100 config.

Should i write a validation callpoint and loop through all of the list ?  
or simply i can use a must constraint  
/listname/\*/leaf/value ?

Also how do i trigger the must constraint only during deletion ?

Many Thanks.

---

<div class="post-metadata">

**Author:** ![cohult](https://yyz2.discourse-cdn.com/flex010/user_avatar/dmap-community.ductus.global/cohult/32/221_2.png) [@cohult](https://dmap-community.ductus.global/u/cohult)\
**Post date:** [June 11, 2020, 8:05am UTC](https://dmap-community.ductus.global/t/wildcard-card-in-a-xpath-of-must-constraint/3097/2 "2020-06-11T08:05:13Z")

</div>

A YANG example instead of some CLI config would be more helpful.

But from what I can tell from your description, as you want to do the check for a certain operation, delete the standalone leaf, you need to use a validation point.

must expressions validate if a new config is valid. It doesn’t compare the new config with the old config being replaced, i.e. take into account what operation (here delete) is used.

---

<div class="post-metadata">

**Author:** ![nandakm](https://avatars.discourse-cdn.com/v4/letter/n/c0e974/32.png) [@nandakm](https://dmap-community.ductus.global/u/nandakm)\
**Post date:** [June 11, 2020, 2:28pm UTC](https://dmap-community.ductus.global/t/wildcard-card-in-a-xpath-of-must-constraint/3097/3 "2020-06-11T14:28:35Z")

</div>

@cohult,

Here is a more detailed explanation.of course this is more simplified version. but it conveys the point i guess

```java
  list vrf {
    key "idx";
    leaf idx { type uint32; }
    container route-leak {
      list name { 
        key "name" ;   
        leaf name { type string; }
        container from {
          list vrf {
            key "idx";
            leaf idx { type uint32; } 
          }
        }
      }
    }
  }

```

Here when you delete a vrf index , we should check if any entry in “from–vrf” in any element in route-leak refers this.

If its referring , we should prohitbit.

Thanks in advance.

---

<div class="post-metadata">

**Author:** ![mvf](https://yyz2.discourse-cdn.com/flex010/user_avatar/dmap-community.ductus.global/mvf/32/182_2.png) [@mvf](https://dmap-community.ductus.global/u/mvf)\
**Post date:** [June 12, 2020, 3:06pm UTC](https://dmap-community.ductus.global/t/wildcard-card-in-a-xpath-of-must-constraint/3097/4 "2020-06-12T15:06:49Z")

</div>

I agree that you cannot use `must` or `leafref` - what you want is to validate an operation, not the resulting configuration (which is somewhat against YANG principles, by the way). I don’t think you can use standard validation callback either - technically they can be used to compare current and new configurations, but it looks to me that in this case it is not possible or at least it would be difficult.

You may want to have a look at transaction hooks - you can declare a transaction hook on the `vrf` list and register a `remove` callback in which you would check if there is a reference to the instance that is being deleted and let the transaction fail if it is. The check might be done using XPath expressions for better performance.

---

<div class="post-metadata">

**Author:** ![cohult](https://yyz2.discourse-cdn.com/flex010/user_avatar/dmap-community.ductus.global/cohult/32/221_2.png) [@cohult](https://dmap-community.ductus.global/u/cohult)\
**Post date:** [June 12, 2020, 8:38pm UTC](https://dmap-community.ductus.global/t/wildcard-card-in-a-xpath-of-must-constraint/3097/5 "2020-06-12T20:38:36Z")

</div>

I believe one should wait until the prepare phase and do that type of check from there.  
Perhaps using get\_modifications() from a prepare phase subscriber.  
Validation should be done on the data (not operations) in YANG model checks, e.g. must expressions, and validataion code. Operations, tests etc should be done in the prepare phase, e.g. from a prepare phase subscriber.

The reason for that is that aborting the transaction from a transaction-hook will not enable you to provide the proper error message (the transaction hook is not meant to be used for validation), while an abort in the prepare phase will. The examples.confd/cdb\_subscription/twophase example that comes with ConfD provide guidance.

---

<div class="post-metadata">

**Author:** ![nandakm](https://avatars.discourse-cdn.com/v4/letter/n/c0e974/32.png) [@nandakm](https://dmap-community.ductus.global/u/nandakm)\
**Post date:** [June 12, 2020, 8:56pm UTC](https://dmap-community.ductus.global/t/wildcard-card-in-a-xpath-of-must-constraint/3097/6 "2020-06-12T20:56:18Z")

</div>

> [@cohult](#):
>
> The reason for that is that aborting the transaction from a transaction-hook will not enable you to provide the proper error message (the transaction hook is not meant to be used for validation), while an abort in the prepare phase will. The examples.confd/cdb\_subscription/twophase example that comes with ConfD provide guidance

Great . Thanks Conny

---

<div class="post-metadata">

**Author:** ![nandakm](https://avatars.discourse-cdn.com/v4/letter/n/c0e974/32.png) [@nandakm](https://dmap-community.ductus.global/u/nandakm)\
**Post date:** [June 12, 2020, 11:19pm UTC](https://dmap-community.ductus.global/t/wildcard-card-in-a-xpath-of-must-constraint/3097/7 "2020-06-12T23:19:15Z")

</div>

@mvf @cohult  
Thanks for the replies.

Im still unsure why a prepare phase is preferred than the validation ? (apart from the error message )  
If validation phase is still an option,  
Does the validation phase have the view of resulting config ?  
Can i write a validation hook

If Prepare phase is the way to go ,  
Do i get the view of CDB snapshot just at the cdb\_diff\_iterate stage,

e.g  
if a transaction already contains both config  
no vrf A  
no rout-leak blah from vrf A.  
Does the CDB already reflect both configs at that point ?

---

<div class="post-metadata">

**Author:** ![cohult](https://yyz2.discourse-cdn.com/flex010/user_avatar/dmap-community.ductus.global/cohult/32/221_2.png) [@cohult](https://dmap-community.ductus.global/u/cohult)\
**Post date:** [June 13, 2020, 6:33am UTC](https://dmap-community.ductus.global/t/wildcard-card-in-a-xpath-of-must-constraint/3097/8 "2020-06-13T06:33:39Z")

</div>

> [@nandakm](#):
>
> Im still unsure why a prepare phase is preferred than the validation ?

I have to correct myself. The validation phase using a validation point is actually what you want here. One of the reasons for that is if someone decides to just validate without committing the configuration, you then too want to run your validation code.

> [@nandakm](#):
>
> Does the validation phase have a view of the resulting config?

To read the old configuration use the CDB API. To get the new configuration use MAAPI. Note that maapi\_diff\_iterate() will not show the old value in the validation phase. The “oldv” passed to the iter() function by maapi\_diff\_iterate() will always be null. You will have to use the CDB API and cdb\_get\_\*() to get the old value(s).

> [@nandakm](#):
>
> (apart from the error message )

The error message handling is there for both the validation point and the prepare phase subscriber. I was referring to the transaction-hook and how the transaction-hook is not where you want to validate and abort a transaction.

---

<div class="post-metadata">

**Author:** ![nandakm](https://avatars.discourse-cdn.com/v4/letter/n/c0e974/32.png) [@nandakm](https://dmap-community.ductus.global/u/nandakm)\
**Post date:** [June 13, 2020, 1:39pm UTC](https://dmap-community.ductus.global/t/wildcard-card-in-a-xpath-of-must-constraint/3097/9 "2020-06-13T13:39:34Z")

</div>

@conny @mvf,  
ok So valiadtion phase the way to go …  
Can i write the validation hooks , using erlang also ?  
If so are there any examples ?  
Is it the same as transactional hook?

---

<div class="post-metadata">

**Author:** ![cohult](https://yyz2.discourse-cdn.com/flex010/user_avatar/dmap-community.ductus.global/cohult/32/221_2.png) [@cohult](https://dmap-community.ductus.global/u/cohult)\
**Post date:** [June 13, 2020, 2:03pm UTC](https://dmap-community.ductus.global/t/wildcard-card-in-a-xpath-of-must-constraint/3097/10 "2020-06-13T14:03:32Z")

</div>

It is not a hook or similar to a transaction-hook. See ConfD UG Chapter “Validation Points” and the confd\_lib\_dp(3) man page section "“Validation Callbacks”

You can find some sort of Erlang econfd reference here:

```auto
$ pwd
/Users/tailf/confd-7.3.2
$ find ./erlang/econfd/examples/ -name "*.yang" |xargs grep validate 
./erlang/econfd/examples//test/smp.yang: tailf:validate vp1;
./erlang/econfd/examples//test/smp.yang: tailf:validate vp2;
$ find ./erlang/econfd/examples/ -name "*.erl" |xargs grep vp1
./erlang/econfd/examples//test/test.erl: ?line V = #confd_valpoint_cb{valpoint = vp1,
$ find ./erlang/econfd/examples/ -name "*.erl" |xargs grep vp2
./erlang/econfd/examples//test/test.erl: ?line V2 = #confd_valpoint_cb{valpoint = vp2,

```

---

<div class="post-metadata">

**Author:** ![nandakm](https://avatars.discourse-cdn.com/v4/letter/n/c0e974/32.png) [@nandakm](https://dmap-community.ductus.global/u/nandakm)\
**Post date:** [June 15, 2020, 1:08pm UTC](https://dmap-community.ductus.global/t/wildcard-card-in-a-xpath-of-must-constraint/3097/11 "2020-06-15T13:08:37Z")

</div>

Thanks @cohult

Just to be clear iun future .  
The transaction cycle from the Confd UG

start -\> READ -\> validate -\> write -\> Prepared -Commit /Abort.

Where in the sequence the Transactional and Transformational Hooks are called ?

---

<div class="post-metadata">

**Author:** ![cohult](https://yyz2.discourse-cdn.com/flex010/user_avatar/dmap-community.ductus.global/cohult/32/221_2.png) [@cohult](https://dmap-community.ductus.global/u/cohult)\
**Post date:** [June 15, 2020, 3:29pm UTC](https://dmap-community.ductus.global/t/wildcard-card-in-a-xpath-of-must-constraint/3097/12 "2020-06-15T15:29:44Z")

</div>

Just set the developer log level to “trace”, execute a transaction, and check the log for what was done for your confd.conf setup and applications. Example:

applying transaction…  
entering validate phase for running…  
grabbing transaction lock…  
grabbing transaction lock ok  
creating rollback file…  
creating rollback file ok  
`run transforms and transaction hooks...`  
`run transforms and transaction hooks done`  
pre validate…  
pre validate done  
run validation over the changeset…  
run validation over the changeset done  
run dependency-triggered validation…  
run dependency-triggered validation done  
leaving validate phase for running  
entering write-start phase for running…  
cdb: write-start  
check data kickers…  
check data kickers done  
leaving write-start phase for running  
entering prepare phase for running…  
cdb: prepare  
leaving prepare phase for running  
entering commit phase for running…  
cdb: commit  
releasing transaction lock  
leaving commit phase for running  
applying transaction done

---

<div class="post-metadata">

**Author:** ![mvf](https://yyz2.discourse-cdn.com/flex010/user_avatar/dmap-community.ductus.global/mvf/32/182_2.png) [@mvf](https://dmap-community.ductus.global/u/mvf)\
**Post date:** [June 16, 2020, 9:03am UTC](https://dmap-community.ductus.global/t/wildcard-card-in-a-xpath-of-must-constraint/3097/13 "2020-06-16T09:03:54Z")

</div>

Let me summarize some differences between transaction hooks and validation, as applied to this use case:

Validation callbacks in general are the _right thing_ for validation. They are invoked when all changes are complete, pretty much just before they are written to CDB; and as Conny pointed out, they are also invoked when the operator asks for mere validation (e.g. using `validate` CLI command or `test-only` NETCONF message). There are some problems with validations in your case though:

- you need to declare `tailf:validate` on the `from-vrf` node, not on the top `vrf` node, but with dependencies on it - this might somewhat counterintuitive;

- your validation callback will not be simple to write - you need to compare the list of `vrf` instances in the transaction with the list of `vrf` instance in CDB to find which ones have been deleted, and then verify that no `from-vrf` instance refers to one of them.

The second point is related to that validation callbacks are tailored to validate configurations, but you are trying to validate an operation.

Now for transaction hooks: in a `remove` callback as described in the other post you immediately know that a `vrf` instance is being deleted - as a result, your code would be much simpler (in particular, no need to open CDB session). But then again, transaction hooks are supposed to serve a bit different role then to validate, so it comes with a price:

- as mentioned, they are not invoked for mere validations, and I believe they are not invoked for transactions targeting candidate datastore;

- there is no guarantee that when a callback “validates” the configuration (or the operation), another callback in the same transaction does not make the configuration invalid, e.g. by configuring `from-vrf` instance.

And then there are prepare-phase subscribers, as mentioned by Conny. I would say they stay somewhere between those two - both in resulting code complexity as well as in other drawbacks. Not sure if there is any reason to pick that instead of a validation callback (or a transaction hook).

---

<div class="post-metadata">

**Author:** ![mvf](https://yyz2.discourse-cdn.com/flex010/user_avatar/dmap-community.ductus.global/mvf/32/182_2.png) [@mvf](https://dmap-community.ductus.global/u/mvf)\
**Post date:** [June 16, 2020, 9:04am UTC](https://dmap-community.ductus.global/t/wildcard-card-in-a-xpath-of-must-constraint/3097/14 "2020-06-16T09:04:22Z")

</div>

One more comment: is it possible to rethink the use case? As said, it goes somewhat against YANG and transactionality principles, plus it has some unclear corner cases: for instance, what constitutes invalid “remove” operation - is it valid to remove a `vrf` instance and in the same transaction add a reference to it? Is it valid if the operations are done in this order, and invalid if done in the opposite order?
