client.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. // Copyright (c) 2017 Arista Networks, Inc.
  2. // Use of this source code is governed by the Apache License 2.0
  3. // that can be found in the COPYING file.
  4. package gnmi
  5. import (
  6. "context"
  7. "crypto/tls"
  8. "crypto/x509"
  9. "fmt"
  10. "io/ioutil"
  11. "strings"
  12. pb "github.com/openconfig/gnmi/proto/gnmi"
  13. "google.golang.org/grpc"
  14. "google.golang.org/grpc/credentials"
  15. "google.golang.org/grpc/metadata"
  16. )
  17. const (
  18. defaultPort = "6030"
  19. )
  20. // Config is the gnmi.Client config
  21. type Config struct {
  22. Addr string
  23. CAFile string
  24. CertFile string
  25. KeyFile string
  26. Password string
  27. Username string
  28. TLS bool
  29. }
  30. // Dial connects to a gnmi service and returns a client
  31. func Dial(cfg *Config) (pb.GNMIClient, error) {
  32. var opts []grpc.DialOption
  33. if cfg.TLS || cfg.CAFile != "" || cfg.CertFile != "" {
  34. tlsConfig := &tls.Config{}
  35. if cfg.CAFile != "" {
  36. b, err := ioutil.ReadFile(cfg.CAFile)
  37. if err != nil {
  38. return nil, err
  39. }
  40. cp := x509.NewCertPool()
  41. if !cp.AppendCertsFromPEM(b) {
  42. return nil, fmt.Errorf("credentials: failed to append certificates")
  43. }
  44. tlsConfig.RootCAs = cp
  45. } else {
  46. tlsConfig.InsecureSkipVerify = true
  47. }
  48. if cfg.CertFile != "" {
  49. if cfg.KeyFile == "" {
  50. return nil, fmt.Errorf("please provide both -certfile and -keyfile")
  51. }
  52. cert, err := tls.LoadX509KeyPair(cfg.CertFile, cfg.KeyFile)
  53. if err != nil {
  54. return nil, err
  55. }
  56. tlsConfig.Certificates = []tls.Certificate{cert}
  57. }
  58. opts = append(opts, grpc.WithTransportCredentials(credentials.NewTLS(tlsConfig)))
  59. } else {
  60. opts = append(opts, grpc.WithInsecure())
  61. }
  62. if !strings.ContainsRune(cfg.Addr, ':') {
  63. cfg.Addr += ":" + defaultPort
  64. }
  65. conn, err := grpc.Dial(cfg.Addr, opts...)
  66. if err != nil {
  67. return nil, fmt.Errorf("failed to dial: %s", err)
  68. }
  69. return pb.NewGNMIClient(conn), nil
  70. }
  71. // NewContext returns a new context with username and password
  72. // metadata if they are set in cfg.
  73. func NewContext(ctx context.Context, cfg *Config) context.Context {
  74. if cfg.Username != "" {
  75. ctx = metadata.NewOutgoingContext(ctx, metadata.Pairs(
  76. "username", cfg.Username,
  77. "password", cfg.Password))
  78. }
  79. return ctx
  80. }
  81. // NewGetRequest returns a GetRequest for the given paths
  82. func NewGetRequest(paths [][]string) (*pb.GetRequest, error) {
  83. req := &pb.GetRequest{
  84. Path: make([]*pb.Path, len(paths)),
  85. }
  86. for i, p := range paths {
  87. gnmiPath, err := ParseGNMIElements(p)
  88. if err != nil {
  89. return nil, err
  90. }
  91. req.Path[i] = gnmiPath
  92. }
  93. return req, nil
  94. }
  95. // NewSubscribeRequest returns a SubscribeRequest for the given paths
  96. func NewSubscribeRequest(paths [][]string) (*pb.SubscribeRequest, error) {
  97. subList := &pb.SubscriptionList{
  98. Subscription: make([]*pb.Subscription, len(paths)),
  99. }
  100. for i, p := range paths {
  101. gnmiPath, err := ParseGNMIElements(p)
  102. if err != nil {
  103. return nil, err
  104. }
  105. subList.Subscription[i] = &pb.Subscription{Path: gnmiPath}
  106. }
  107. return &pb.SubscribeRequest{
  108. Request: &pb.SubscribeRequest_Subscribe{Subscribe: subList}}, nil
  109. }