openconfig / ygot

A YANG-centric Go toolkit - Go/Protobuf Code Generation; Validation; Marshaling/Unmarshaling
Apache License 2.0
286 stars 107 forks source link

Eroor Generating GoStruct Code: duplicate entry label at the root #504

Closed lyckety closed 3 years ago

lyckety commented 3 years ago

Good day! I have a device that supports configuration via netconf. Yang-files look like this:

switch.yang

module switch {
  yang-version 1;
  namespace "urn:example.com:switch";
  prefix tc;

  import port { prefix port; }
  import lag { prefix lag; }

  revision 2021-01-01 {
  }

  typedef port-ref {
    type port:ref;
  }

  typedef lag-ref {
    type lag:ref;
  }
}

port.yang

module port {
  yang-version 1;
  namespace "urn:example.com:port";
  prefix port;

  typedef ref {
    type leafref {
      path "/port:label/port:name";
    }
  }

  list label {
    key name;
    unique "number port";
    leaf name {
      type string;
    }
  }
}

lag.yang

module lag {
  yang-version 1;
  namespace "urn:example.com:lag";
  prefix lag;

  import port { prefix port; }

  revision 2021-01-01 {
    description "init";
  }

  typedef ref {
    type leafref {
      path "/lag:label/lag:name";
    }
  }

  list label {
    key name;
    leaf name {
      type string;
    }
    container members {
      leaf-list port {
        type port:ref;
      }
    }
  }
}

When trying to generate go structures with fakeroot using this command:

go run ${HOME}/go/src/github.com/openconfig/ygot/generator/generator.go \
    -annotations=false \
    -generate_fakeroot -fakeroot_name=switch \
    -output_file=switch.go  \
    -package_name=switch \
    ./yang-models/lag/lag.yang \
    ./yang-models/port/port.yang \
    ./yang-models/switch/switch.yang

i get an error:

F0309 20:31:26.265651  557575 generator.go:352] ERROR Generating GoStruct Code: duplicate entry label at the root: exists: /lag/label, new: /port/label

How can I solve this problem? Thanks!

wenovus commented 3 years ago

I believe the issue here is that ygot merges all the modules contents into a single fake root, causing the two labels to conflict. This means ygot currently imposes a more restrictive requirement than YANG, where uniqueness has to be ensured across all modules' top-levels instead of just within a module.

One way to solve the issue, and is often used by OpenConfig, would be to put everything within each module inside a container, in this case "lag" and "port". They would cause ygot to generate another layer of hierarchy that avoids the conflict.

lyckety commented 3 years ago

Thank you for your quick response and recommendation.

It would be nice if, when generating fakeroot in the future, it would be possible to solve this problem using an additional parameter. For example, in my case, structures with the names "PortLabel", "LagLabel" were created in fakeroot