openconfig / ygot

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

Is there a way to add custom struct tags on generated GoStructs? #522

Open soumiksamanta opened 3 years ago

soumiksamanta commented 3 years ago
// Interface represents the /openconfig-interfaces/interfaces/interface YANG schema element.
type Interface struct {
        AdminStatus  E_OpenconfigInterfaces_Interface_AdminStatus `path:"state/admin-status" module:"openconfig-interfaces"`
        Counters     *Interface_Counters                          `path:"state/counters" module:"openconfig-interfaces"`
        Description  *string                                      `path:"config/description" module:"openconfig-interfaces"`
        Enabled      *bool                                        `path:"config/enabled" module:"openconfig-interfaces"`
        HoldTime     *Interface_HoldTime                          `path:"hold-time" module:"openconfig-interfaces"`
        Ifindex      *uint32                                      `path:"state/ifindex" module:"openconfig-interfaces"`
        LastChange   *uint32                                      `path:"state/last-change" module:"openconfig-interfaces"`
        Mtu          *uint16                                      `path:"config/mtu" module:"openconfig-interfaces"`
        Name         *string                                      `path:"config/name|name" module:"openconfig-interfaces"`
        OperStatus   E_OpenconfigInterfaces_Interface_AdminStatus `path:"state/oper-status" module:"openconfig-interfaces"`
        Subinterface map[uint32]*Interface_Subinterface           `path:"subinterfaces/subinterface" module:"openconfig-interfaces"`
        Type         E_IETFInterfaces_InterfaceType               `path:"config/type" module:"openconfig-interfaces"`
}

Is there a way where I can generate the struct with custom tags on few fields?

For example, HoldTime having an extra struct tag

// Interface represents the /openconfig-interfaces/interfaces/interface YANG schema element.
type Interface struct {
        AdminStatus  E_OpenconfigInterfaces_Interface_AdminStatus `path:"state/admin-status" module:"openconfig-interfaces"`
        Counters     *Interface_Counters                          `path:"state/counters" module:"openconfig-interfaces"`
        Description  *string                                      `path:"config/description" module:"openconfig-interfaces"`
        Enabled      *bool                                        `path:"config/enabled" module:"openconfig-interfaces"`
        HoldTime     *Interface_HoldTime                          `path:"hold-time" module:"openconfig-interfaces" swaggertype:"string"`
        Ifindex      *uint32                                      `path:"state/ifindex" module:"openconfig-interfaces"`
        LastChange   *uint32                                      `path:"state/last-change" module:"openconfig-interfaces"`
        Mtu          *uint16                                      `path:"config/mtu" module:"openconfig-interfaces"`
        Name         *string                                      `path:"config/name|name" module:"openconfig-interfaces"`
        OperStatus   E_OpenconfigInterfaces_Interface_AdminStatus `path:"state/oper-status" module:"openconfig-interfaces"`
        Subinterface map[uint32]*Interface_Subinterface           `path:"subinterfaces/subinterface" module:"openconfig-interfaces"`
        Type         E_IETFInterfaces_InterfaceType               `path:"config/type" module:"openconfig-interfaces"`
}

This way the same generated GoStruct can be used by other tools.

robshakir commented 3 years ago

There currently isn't a way to do this within ygen, but we'd be happy to discuss a design for doing so.

It seems like there are some complexities with doing this, since you would want to be able to specify a custom set of annotations per field of the generated struct, which means we need to support some way to get those changes. Options for this might be:

I expect that designing the last of these is the most useful, but the most complex, and I think would be something that we would want to do within the context of supporting the IR that we've discussed in other issues, since this would then be something extensible that we could use for different use cases.