1

the following when condition is referring to a non existing node. I wonder why pyang does not throw error ? It does, if I use a wrong prefix though.

can you review the when conditions (embedded in the module) please.

is it allowed (in when expression) to refer to schema out of the augment itself ?

module mod-w-1 {
  namespace "http://example.org/tests/mod-w-1";
  prefix m1;

  container m1 {
    leaf b1 {
      type string;
    }
  }
}

module when-tests {
  namespace "http://example.org/tests/when-tests";
  prefix wt;

  import mod-w-1 {
    prefix m1;
  }

  augment "/m1:m1" {
       // when "/m1:m1/b3 = 'abc'";
       // there is no b3, so, should be invalid.

       // when "/m1:m1/b1 = 'abc'";
       // a payload or data situation that has m1/b1 != 'abc' will cause the 
       // data that fits this augment content will be invalid/rejected.
       /* for ex; 
          <m1>
            <b1>fff</b1>
            <x>sfsf</x>
            <conditional>
              <foo>dddd</foo>
            </conditional>  
          </m1>
          is invalid, hence, the <x> and <conditional> parts will be 
          rejected.
      */   
       leaf x {
         type string;
       }
       container conditional {
          leaf foo {
              type string;
          }
       }
    } 
}
user19937
  • 587
  • 1
  • 7
  • 25

1 Answers1

1

That is because pyang does not validate semantics of XPath expressions at all, only their syntax - and a couple of additional checks, such as function and prefix usage. You will need another YANG compiler to validate those properly.

def v_xpath(ctx, stmt):
    try:
        toks = xpath.tokens(stmt.arg)
        for (tokname, s) in toks:
            if tokname == 'name' or tokname == 'prefix-match':
                i = s.find(':')
                if i != -1:
                    prefix = s[:i]
                    prefix_to_module(stmt.i_module, prefix, stmt.pos,
                                     ctx.errors)
            elif tokname == 'literal':
                # kind of hack to detect qnames, and mark the prefixes
                # as being used in order to avoid warnings.
                if s[0] == s[-1] and s[0] in ("'", '"'):
                    s = s[1:-1]
                    i = s.find(':')
                    # make sure there is just one : present
                    if i != -1 and s[i+1:].find(':') == -1:
                        prefix = s[:i]
                        # we don't want to report an error; just mark the
                        # prefix as being used.
                        my_errors = []
                        prefix_to_module(stmt.i_module, prefix, stmt.pos,
                                         my_errors)
                        for (pos, code, arg) in my_errors:
                            if code == 'PREFIX_NOT_DEFINED':
                                err_add(ctx.errors, pos,
                                        'WPREFIX_NOT_DEFINED', arg)
            elif ctx.lax_xpath_checks == True:
                pass
            elif tokname == 'variable':
                err_add(ctx.errors, stmt.pos, 'XPATH_VARIABLE', s)
            elif tokname == 'function':
                if not (s in xpath.core_functions or
                        s in yang_xpath_functions or
                        (stmt.i_module.i_version != '1' and
                         s in yang_1_1_xpath_functions) or
                        s in extra_xpath_functions):
                    err_add(ctx.errors, stmt.pos, 'XPATH_FUNCTION', s)
    except SyntaxError as e:
        err_add(ctx.errors, stmt.pos, 'XPATH_SYNTAX_ERROR', e)

Line 1993 of statements.py.

Note that an XPath expression referring to a non-existent node is technically not invalid, not from XPath specification perspective. It just means that an empty node set will be selected by the location path (and that your condition will be false forever).

Yes, you can refer to nodes that are "above" the augment's target node or are its siblings - in fact, you always should when when statement is in play (it should not refer to any node made conditional by it).

Also, you should never attempt to break "module confinement" with a non-prefixed node test (such as b3 and b1). The XPath expression is only able to see names that are defined in imports of the defining module and the defining module itself. For example, even if b3 is later augmented by some unknown third module, your condition would still evaluate to false. It is best to assume that non-prefixed names belong to the defining module's namespace.

predi
  • 5,528
  • 32
  • 60
  • hi, thank you. Is there a way I can contact you directly. I probably need a few hours of consultation (I will pay) and you seem to be the only one actively helping on yang related questions. – user19937 Mar 07 '17 at 22:37
  • Are there other yang tools that go beyond what pyang offers. I know about libyang, but, I need a recognized , known to be yang 1.1 compliant and dependable one. Is there any (not that libyang is not those, just, that I want to hear from someone who knows firsthand)? – user19937 Mar 08 '17 at 06:08
  • @user19937, oh, I'm not the only one - I just happen to be the first one to answer and I only answer the questions I know I can answer. NETMOD WG has recently started [compiling](http://www.claise.be/IETFYANGPageCompilation.html) their modules with several compilers (check the list), though I wouldn't know if they are 1.1 compliant. There's a list of NETCONF/YANG related implementations [here](https://trac.ietf.org/trac/netconf). I know MG-SOFT has a YANG toolchain (includes an IDE), has started rolling out support for 1.1 and validates XPath expressions (disclaimer: I'm an employee). – predi Mar 08 '17 at 08:04