go.ligato.io/vpp-agent/v3@v3.5.0/pkg/models/options.go (about) 1 package models 2 3 import ( 4 "net" 5 "strings" 6 "text/template" 7 8 "google.golang.org/protobuf/types/dynamicpb" 9 ) 10 11 type modelOptions struct { 12 nameTemplate string 13 nameFunc NameFunc 14 } 15 16 // ModelOption defines function type which sets model options. 17 type ModelOption func(*modelOptions) 18 19 // NameFunc represents function which can name model instance. 20 type NameFunc func(obj interface{}) (string, error) 21 22 // WithNameTemplate returns option for models which sets function 23 // for generating name of instances using custom template. 24 func WithNameTemplate(t string) ModelOption { 25 return func(opts *modelOptions) { 26 opts.nameFunc = NameTemplate(t) 27 opts.nameTemplate = t 28 } 29 } 30 31 const namedTemplate = `{{.Name}}` 32 33 type named interface { 34 GetName() string 35 } 36 37 func NameTemplate(t string) NameFunc { 38 tmpl := template.Must( 39 template.New("name").Funcs(funcMap).Option("missingkey=error").Parse(t), 40 ) 41 return func(obj interface{}) (string, error) { 42 // handling locally known dynamic messages (they don't have data fields as generated proto messages) 43 // (dynamic messages of remotely known models are not supported, remote_model implementation is 44 // not using dynamic message for name template resolving so it is ok) 45 if dynMessage, ok := obj.(*dynamicpb.Message); ok { 46 var err error 47 obj, err = DynamicLocallyKnownMessageToGeneratedMessage(dynMessage) 48 if err != nil { 49 return "", err 50 } 51 } 52 53 // execute name template on generated proto message 54 var s strings.Builder 55 if err := tmpl.Execute(&s, obj); err != nil { 56 return "", err 57 } 58 return s.String(), nil 59 } 60 } 61 62 var funcMap = template.FuncMap{ 63 "ip": func(s string) string { 64 ip := net.ParseIP(s) 65 if ip == nil { 66 return "<invalid>" 67 } 68 return ip.String() 69 }, 70 "protoip": func(s string) string { 71 ip := net.ParseIP(s) 72 if ip == nil { 73 return "<invalid>" 74 } 75 76 if ip.To4() == nil { 77 return "IPv6" 78 } 79 return "IPv4" 80 }, 81 "ipnet": func(s string) map[string]interface{} { 82 if strings.HasPrefix(s, "alloc:") { 83 // reference to IP address allocated via netalloc 84 return nil 85 } 86 _, ipNet, err := net.ParseCIDR(s) 87 if err != nil { 88 return map[string]interface{}{ 89 "IP": "<invalid>", 90 "MaskSize": 0, 91 "AllocRef": "", 92 } 93 } 94 maskSize, _ := ipNet.Mask.Size() 95 return map[string]interface{}{ 96 "IP": ipNet.IP.String(), 97 "MaskSize": maskSize, 98 "AllocRef": "", 99 } 100 }, 101 }