go.ligato.io/vpp-agent/v3@v3.5.0/examples/tutorials/08_grpc/plugins/grpc/grpc_client.go (about) 1 // Copyright (c) 2019 Cisco and/or its affiliates. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at: 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package grpc 16 17 import ( 18 "context" 19 "io" 20 "net" 21 "time" 22 23 "go.ligato.io/cn-infra/v2/infra" 24 "google.golang.org/grpc" 25 26 "go.ligato.io/vpp-agent/v3/proto/ligato/configurator" 27 "go.ligato.io/vpp-agent/v3/proto/ligato/vpp" 28 vpp_interfaces "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/interfaces" 29 ) 30 31 // Client is aGRPC plugin structure 32 type Client struct { 33 Deps // external dependencies 34 35 connection *grpc.ClientConn 36 client configurator.ConfiguratorServiceClient 37 } 38 39 // Deps is a structure for the plugin external dependencies 40 type Deps struct { 41 infra.PluginDeps 42 } 43 44 // Inti is the initialization function, called when the agent in started 45 func (p *Client) Init() (err error) { 46 p.connection, err = grpc.Dial("unix", 47 grpc.WithInsecure(), 48 grpc.WithDialer(dialer("tcp", "0.0.0.0:9111", time.Second*2)), 49 ) 50 if err != nil { 51 return err 52 } 53 54 p.client = configurator.NewConfiguratorServiceClient(p.connection) 55 56 p.Log.Info("GRPC client is connected") 57 // Start notification watcher 58 go p.watchNotif() 59 go p.configure() 60 61 return nil 62 } 63 64 // Close function, called on the shutdown 65 func (p *Client) Close() (err error) { 66 return nil 67 } 68 69 // String is the GRPC plugin string representation 70 func (p *Client) String() string { 71 return "GRPC-client" 72 } 73 74 // Dialer function used as a parameter for 'grpc.WithDialer' 75 func dialer(socket, address string, timeoutVal time.Duration) func(string, time.Duration) (net.Conn, error) { 76 return func(addr string, timeout time.Duration) (net.Conn, error) { 77 addr, timeout = address, timeoutVal 78 return net.DialTimeout(socket, addr, timeoutVal) 79 } 80 } 81 82 // Configure is a helper struct to demonstrate plugin functionality 83 func (p *Client) configure() { 84 time.Sleep(2 * time.Second) 85 _, err := p.client.Update(context.Background(), &configurator.UpdateRequest{ 86 Update: &configurator.Config{ 87 VppConfig: &vpp.ConfigData{ 88 Interfaces: []*vpp.Interface{ 89 { 90 Name: "interface1", 91 Type: vpp_interfaces.Interface_SOFTWARE_LOOPBACK, 92 Enabled: true, 93 IpAddresses: []string{"10.0.0.1/24"}, 94 }, 95 }, 96 }, 97 }, 98 FullResync: true, 99 }) 100 if err != nil { 101 p.Log.Errorf("Error putting GRPC data: %v", err) 102 return 103 } 104 p.Log.Infof("GRPC data sent") 105 } 106 107 // WatchNotif shows how to implement GRPC notification watcher 108 func (p *Client) watchNotif() { 109 p.Log.Info("Notification watcher started") 110 var nextIdx uint32 111 for { 112 request := &configurator.NotifyRequest{ 113 Idx: nextIdx, 114 } 115 stream, err := p.client.Notify(context.Background(), request) 116 if err != nil { 117 p.Log.Error(err) 118 return 119 } 120 var recvNotifs int 121 for { 122 notif, err := stream.Recv() 123 if err == io.EOF { 124 if recvNotifs == 0 { 125 // Nothing to do 126 } else { 127 p.Log.Infof("%d new notifications received", recvNotifs) 128 } 129 break 130 } 131 if err != nil { 132 p.Log.Error(err) 133 return 134 } 135 136 p.Log.Infof("Notification[%d]: %v", notif.NextIdx-1, notif.Notification) 137 nextIdx = notif.NextIdx 138 recvNotifs++ 139 } 140 141 time.Sleep(time.Second * 1) 142 } 143 }