unique constraints for Yang leaf-list across all nodes in a list - yang

I have below yang models
container PORT {
description "PORT part of config_db.json";
list PORT_LIST {
key "name";
leaf name {
type string {
length 1..128;
}
}
leaf-list lanes {
type string {
length 1..128;
}
}
}
}
And below config
PORT": {
"PORT_LIST": [
{
"name": "Ethernet8",
"lanes": ["65", "66"]
},
{
"name": "Ethernet9",
"lanes": ["65", "67"]
}
]
}
How to add a constraint, 'must' or 'unique' such that elements of leaf-list 'lanes' are unique across all nodes in PORT_LIST. In above example value '65' in 'lanes' field should be allowed only in one node.

The unique statement may only refer to one or more leaf statements, so that is not an option.
You should be able to achieve a similar result with a must statement and a condition like this:
module c {
yang-version 1.1;
namespace "c:uri";
prefix "c";
container PORT {
description "PORT part of config_db.json";
list PORT_LIST {
key "name";
must "count(lanes[current()/preceding-sibling::PORT_LIST/lanes = .]) = 0" {
error-message "Lanes entries must be unique accross all entries of PORT_LIST";
}
leaf name {
type string {
length 1..128;
}
}
leaf-list lanes {
type string {
length 1..128;
}
}
}
}
}
The condition says something along the lines of: if there are any lanes for this PORT_LIST entry, none of them should have the same value as the lanes in any of the PORT_LIST entries that come before this one.
<?xml version="1.0" encoding="utf-8"?>
<config xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
<PORT xmlns="c:uri">
<PORT_LIST>
<name>Ethernet8</name>
<lanes>65</lanes>
<lanes>66</lanes>
</PORT_LIST>
<PORT_LIST>
<name>Ethernet9</name>
<lanes>65</lanes>
<lanes>67</lanes>
</PORT_LIST>
</PORT>
</config>
Error at (9:5): failed assert at "/nc:config/c:PORT/c:PORT_LIST": Lanes entries must be unique accross all entries of PORT_LIST
This is just a quick example, there may be more efficient ways to define the condition.

Related

Query variables in Dgraph filter

I am trying to use a variables (which is a scalar) in a #filter(ge(...)) call, but I run into an error
Given the following query
{
ua(func: uid(0xfb7f7)) {
uid
start_ua {
sua as index
}
recorded_in {
actions #filter(ge(index, sua)){
index
}
}
}
}
I get the following error
{
"errors": [
{
"code": "ErrorInvalidRequest",
"message": "Some variables are defined but not used\nDefined:[sua]\nUsed:[]\n"
}
],
"data": null
}
Now if I remove the sua as ... and the #filter(...) from the query, all works fine.
My Dgraph version is v1.0.13.
I tried replacing #filter(ge(index, sua)) with #filter(ge(index, val(sua))) but I still run into an error:
{
"errors": [
{
"code": "ErrorInvalidRequest",
"message": ": No value found for value variable \"sua\""
}
],
"data": null
}
What am I doing wrong?
Here's what the Dgraph docs say about value variables (emphasis added): https://docs.dgraph.io/query-language/#value-variables
Value variables store scalar values. Value variables are a map from the UIDs
of the enclosing block to the corresponding values.
It therefore only makes sense to use the values from a value variable in a
context that matches the same UIDs - if used in a block matching different
UIDs the value variable is undefined.
The start_ua and recorded_in are different subgraphs, which means variables defined in one are undefined in the other within the same query block.
What you can do is use multiple query blocks. Variables can be accessed across blocks:
{
block1(func: uid(0xfb7f7)) {
uid
start_ua (first: 1) {
sua as index
}
}
block2(func: uid(0xfb7f7)) {
recorded_in {
actions #filter(ge(index, val(sua))) {
index
}
}
}
}
I also added (first: 1) to the start_ua predicate, so that at most 1 node is fetched and stored the sua variable. If your data is already structured that way, then that's not needed.
val(sua) gets the value of the variable sua.

YANG - Modeling non-mandatory containers

Currently I am working with YANG as part of a (legacy) Python project.
I am somewhat stuck at the task of defining a schema, which shall then be used to verify data, organized as a Python dictionary.
If it is possible, I would "like" to keep the current structure, since a lot of the codebase is using this data.
An "unaltered" piece of data:
"namespace": { # Mandatory
"management": { # Optional
"interfaces": { # Mandatory
"m0": { # Optional
"leaf1": "..."
}
}
},
"benchmark": { # Optional
"interfaces": { # Mandatory
"b0": { # Optional
"leaf1": "...",
"leaf2": "..."
},
"b1": { # Optional
"leaf1": "...",
"leaf2": "..."
}
}
}
}
My problem is that everything marked as "optional" (in the example) would be modeled as a container but it seems that they cannot be defined as optional (i.e.: mandatory false;) according to RFC6020.
Therefore, I defined a model that is using lists. Meaning some nodes of the Python Dict (management, benchmark, m0, b0, b1) are now list elements and cannot be accessed in the current fashion, e.g.: data['namespace']['management']...
The modified example looks like this:
"namespace": [
{
"desc": "management",
"interfaces": [
{
"leaf1": "..."
}
]
},
{
"desc": "benchmark",
"interfaces": [
{
"leaf1": "...",
"leaf2": "..."
},
{
"leaf1": "...",
"leaf2": "..."
}
]
}
]
The describing (snippet from my current) YANG model:
list namespace {
description "Namespace definitions.";
key desc;
leaf desc { type string; }
uses leaf-definitions;
list interfaces {
key leaf1;
uses leaf-definitions;
}
}
The verification is successful and the conversion of the data (itself) is not a problem, but it is resulting in a big pile of broken code.
This leads to my question(s):
Am I correct - are containers in YANG always mandatory?
Is there maybe another way to model this scenario? (Without breaking "too much")
I am very thankful for your input, since I am rather new to YANG!
Am I correct - are containers in YANG always mandatory?
Quite the contrary. They are always optional, unless they contain mandatory nodes (mandatory leaf, a list or leaf-list with min-elements > 0, etc.). In other words, containers inherit this property from their descendants. This of course only applies to non-presence containers. A presence container with mandatory children does not inherit this property, since that would defeat its purpose (presence). You probably missed the definition of a mandatory node in RFC6020:
A mandatory node is one of:
o A leaf, choice, or anyxml node with a "mandatory" statement with
the value "true".
o A list or leaf-list node with a "min-elements" statement with a
value greater than zero.
o A container node without a "presence" statement, which has at
least one mandatory node as a child.
This should already be helpful for your second question.
Is there maybe another way to model this scenario? (Without breaking "too much")
Abuse presence containers. They are always optional. You could also probably avoid using the lists by introducing some mandatory children to a non-presence container. Based on your initial data:
module mandatory-optional-branch {
namespace "org:example:mandatory-optional-branch";
prefix "mob";
grouping leafs {
leaf leaf1 {type string;}
leaf leaf2 {type string;}
}
list namespace { // mandatory
config false;
min-elements 1;
max-elements 1;
container management { // optional by nature
presence "I have mandatory children, but am not mandatory. Yay for me.
Of course my presence should have some meaning.";
list interfaces { // mandatory
min-elements 1;
max-elements 1;
container m0 { // optional - no mandatory node children
leaf leaf1 {type string;}
}
}
}
container benchmark { // optional by nature
presence "Same as 'management' above.";
list interfaces { // mandatory
min-elements 1;
max-elements 1;
container b0 { // optional - no mandatory node children
uses leafs;
}
container b1 { // optional - no mandatory node children
uses leafs;
}
}
}
}
}

Mongodb group by on internal element

I have data in following format
{
_id:ObjectId("someid"),
"masterKey":{
"key1":"val1",
"key2":"val2",
"key3":"val3",
"key4":"val1",
"key5":"val2",
"key6":"val3",
}
}
And I am expecting result which group the duplicate values of master key.
The result should be similar to this. Or in any other format which finds duplicate values of keys with key name.
{
_id:Object("someid"),
"masterKey":{
"val1":["key1","key4"],
"val2":["key2","key5"],
"val3":["key3","key6"]
}
}

Query key with value anywhere in object hierarchy in Mongo

In Mongo how can I find all documents that have a given key and value, regardless of where that key appears in the document's key/value hierarchy?
For example the input key roID and value 5 would match both:
{
roID: '5'
}
and
{
other: {
roID: '5'
}
}
There is no built in way to do this. You might have to scan each matched document recursively to try and locate that attribute. Not recommended. You might want to think about restructuring your data or perhaps manipulating it into a more unified format so that it will be easier (and faster) to query.
If your desired key appears in a fixed number of different locations, you could use the $or operator to scan all the possibilities.
Taking your sample documents as an example, your query would look something like this:
db.data.find( { "$or": [
{ "roID": 5 },
{ "other.roID": 5 },
{ "foo.bar.roID": 5 },
{ any other possbile locations of roID },
...
] } )
If the number of documents in collection is not so large, then it can be done by this:
db.system.js.save({_id:"keyValueExisted", value: function (key, value) {
function findme(obj) {
for (var x in obj) {
var v = obj[x];
if (x == key && v == value) {
return true;
} else if (v instanceof Object) {
if (findme(v)) return true;
}
}
return false;
}
return findme(this);
}});
var param = ['roID', '5'];
db.c.find({$where: "keyValueExisted.apply(this, " + tojsononeline(param) + ");"});

Detect empty pick() from hash in KRL

I have a bunch of data in a hash and I am picking from it. Sometimes there will be data there to pick and sometimes there won't. What is the best way to know when there was something found by the pick operator and when there wasn't so I can react to that in my code?
The pick operator will take a second optional parameter that will make it so that it always returns the results in an array. This means that if something is picked, the length of the array will be greater than 0, otherwise it will be 0. You can then use that to do what you are wanting to do.
Example code/app taken from http://kynetxappaday.wordpress.com/2011/01/04/day-30-detecting-empty-pick/
ruleset a60x526 {
meta {
name "hash-pick-detect"
description <<
hash-pick-detect
>>
author "Mike Grace"
logging on
}
global {
dataHash = {
"one": {
"name": "Mike"
}, // number
"two": {
"random": 8
}, // number
"three": {
"name": "Alex"
} // number
}; // dataHash
} // global
rule detect_the_pick {
select when pageview ".*"
foreach dataHash setting (key, value)
pre {
userName = value.pick("$.name", true);
length = userName.length();
}
if (length > 0) then {
notify("Key: #{key}","Name: #{userName}<br/>Length: #{length}") with sticky = true;
}
notfired {
raise explicit event empty_pick
with pickedKey = key;
}
}
rule empty_pick_found {
select when explicit empty_pick
pre {
pickedKey = event:param("pickedKey");
results =<<
Key: #{pickedKey}<br/>
doesn't have a name associated with it to pick from
>>; //' fixing syntax highlighting
}
{
notify("An empty pick was detected",results) with sticky = true;
}
}
}