Skip to content

Instantly share code, notes, and snippets.

@colinmcintosh
Last active February 14, 2020 06:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save colinmcintosh/0feaadd40c1821471dcc7024e2e68212 to your computer and use it in GitHub Desktop.
Save colinmcintosh/0feaadd40c1821471dcc7024e2e68212 to your computer and use it in GitHub Desktop.
This is an example of how to use github.com/openconfig/goyang to determine the modeled type of an OpenConfig path
// Copyright 2020 Netflix Inc
// Author: Colin McIntosh (colin@netflix.com)
// Copyright 2015 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// This is an example of how to use github.com/openconfig/goyang to determine the modeled type of an OpenConfig path.
// Example Usage: go run yang_type.go -search=~/go/src/github.com/openconfig/public -path=/interfaces/interface/state/counters/out-octets
package main
import (
"flag"
"fmt"
"github.com/openconfig/goyang/pkg/yang"
"os"
"path/filepath"
"sort"
"strings"
)
func main() {
searchPath := flag.String("search", "", "Directory containing your clone of github.com/openconfig/public")
queryPath := flag.String("path", "", "Path lookup the type of.")
flag.Parse()
if *searchPath == "" {
fmt.Println("You must specify -search")
flag.PrintDefaults()
os.Exit(1)
}
if *queryPath == "" {
fmt.Println("You must specify -path")
flag.PrintDefaults()
os.Exit(1)
}
// Load all of the OpenConfig root entries. This ignores non-openconfig-prefixed files
entries := loadAllModules(*searchPath)
root := make(map[string]*yang.Entry)
for fileName, fileEntry := range entries {
if strings.HasPrefix(fileName, "openconfig") {
for name, rootEntry := range fileEntry.Dir {
root[name] = rootEntry
}
}
}
// Print sorted list of all of the available root entries
//keys := make([]string, 0, len(root))
//for k := range root {
// keys = append(keys, k)
//}
//sort.Strings(keys)
//for _, k := range keys {
// fmt.Println(k)
//}
fmt.Println(GetTypeByPath(root, strings.Split(strings.Trim(*queryPath, "/"), "/")))
}
func GetTypeByPath(root map[string]*yang.Entry, path []string) string {
entry, exists := root[path[0]]
if exists {
return getTypeByPath(entry, path[1:])
}
return ""
}
func getTypeByPath(entry *yang.Entry, path []string) string {
child, exists := entry.Dir[path[0]]
if exists {
if len(path) == 1 {
return child.Type.Name
}
return getTypeByPath(entry.Dir[path[0]], path[1:])
} else {
return ""
}
}
// Portions of this are originally from github.com/openconfig/goyang/yang.go
func loadAllModules(searchPath string) map[string]*yang.Entry {
expanded, err := yang.PathsWithModules(searchPath)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
yang.AddPath(expanded...)
var fileList []string
err = filepath.Walk(searchPath,
func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if strings.HasSuffix(info.Name(), ".yang") {
fileList = append(fileList, strings.TrimSuffix(info.Name(), ".yang"))
}
return nil
})
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
ms := yang.NewModules()
for _, fileName := range fileList {
if err := ms.Read(fileName); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}
// Process the read files, exiting if any errors were found.
_ = ms.Process()
// Keep track of the top level modules we read in.
// Those are the only modules we want to print below.
mods := map[string]*yang.Module{}
var names []string
for _, m := range ms.Modules {
if mods[m.Name] == nil {
mods[m.Name] = m
names = append(names, m.Name)
}
}
sort.Strings(names)
entries := make(map[string]*yang.Entry, len(names))
for _, name := range names {
entries[name] = yang.ToEntry(mods[name])
}
return entries
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment