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  }