Skip to content

Commit

Permalink
Fix context passing
Browse files Browse the repository at this point in the history
  • Loading branch information
nleiva committed May 12, 2022
1 parent 5bf8742 commit 69a348c
Show file tree
Hide file tree
Showing 13 changed files with 45 additions and 122 deletions.
59 changes: 12 additions & 47 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -744,36 +744,11 @@ Cisco-IOS-XR-ipv4-bgp-act.yang
Cisco-IOS-XR-ipv4-ospf-act.yang
Cisco-IOS-XR-ipv4-ping-act.yang
Cisco-IOS-XR-ipv4-traceroute-act.yang
Cisco-IOS-XR-ipv6-ospfv3-act.yang
Cisco-IOS-XR-ipv6-ping-act.yang
Cisco-IOS-XR-ipv6-traceroute-act.yang
Cisco-IOS-XR-isis-act.yang
Cisco-IOS-XR-lib-keychain-act.yang
Cisco-IOS-XR-ping-act.yang
Cisco-IOS-XR-snmp-test-trap-act.yang
Cisco-IOS-XR-syslog-act.yang
Cisco-IOS-XR-sysmgr-act.yang
Cisco-IOS-XR-traceroute-act.yang
Cisco-IOS-XR-upgrade-fpd-ng-act.yang
...
```
#### Ping
- IPv4 Ping (`example/action` with [ping4.json](example/input/action/ping4.json))
```console
$ ./action -act "../input/action/ping4.json"
output from [2001:420:2cff:1204::7816:1]:57344
{
"Cisco-IOS-XR-ping-act:output": {...}
}
2018/05/29 15:03:19 This process took 762.440427ms
```
![ipv4-ping](https://github.com/nleiva/xrgrpc/blob/gh-pages/static/images/ipv4_ping.svg)
- IPv6 Ping (`example/action` with [ping6.json](example/input/action/ping6.json))
```console
Expand Down Expand Up @@ -928,12 +903,16 @@ router, err := xr.BuildRouter(
The following is the configuration required on the IOS XR device in order to enable gRPC dial-in with TLS support.
```
!! IOS XR Configuration version = 6.2.2
grpc
port 57344
tls
tpa
vrf default
address-family ipv4
default-route mgmt
!
!
address-family ipv6
!
grpc
port 57777
address-family ipv4
!
```
Expand All @@ -949,21 +928,7 @@ mrstn-5502-1 emsd: [1058]: %MGBL-EMS-4-EMSD_PORT_RANGE : The configured port 565
Update 6/24/2019: You no longer need to download the certicate file manually. If you don't specify a file, it will be downloaded automatically as in the [getconfig](example/getconfig/main.go) example.
You can optionally retrive the `ems.pem` file from the IOS XR device (after enabling gRPC/TLS) and put it in the [input](example/input) folder (or any other location specified in [config.json](example/input/config.json)). You can find the file in the router on either `/misc/config/grpc/` or `/var/xr/config/grpc`.
- /var/xr/config/grpc
```console
$ ls -la
total 20
drwxr-xr-x 3 root root 4096 Jul 5 17:47 .
drwxr-xr-x 10 root root 4096 Jul 3 12:50 ..
drwx------ 2 root root 4096 Jul 3 12:50 dialout
-rw------- 1 root root 1675 Jul 5 17:47 ems.key
-rw-rw-rw- 1 root root 1513 Jul 5 17:47 ems.pem
```
### Self-signed certificate for testing
### Self-signed certificate for package testing
This needs to be renewed once a year.
Expand Down Expand Up @@ -1004,7 +969,7 @@ $ protoc --go_out=. \
proto/telemetry/lldp/lldp_neighbor.proto
```
## Running the Examples
## Running the examples
After cloning the repo, go the a folder example and execute `go run main.go`. For example:
Expand Down
76 changes: 16 additions & 60 deletions client.go
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
package xrgrpc

import (
"context"
"crypto/tls"
"errors"
"fmt"
"io"
"net"
"os"
"strconv"
"time"
"errors"
"context"

pb "github.com/nleiva/xrgrpc/proto/ems"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/credentials/insecure"
)

// CiscoGrpcClient identifies the parameters for gRPC session setup.
Expand All @@ -39,7 +40,7 @@ func NewDevices() *Devices {
// RouterOption is a funcion that sets one or more options for a given target.
type RouterOption func(r *CiscoGrpcClient) error

// BuildRouter is a traget constructor with options.
// BuildRouter is a target constructor with options.
func BuildRouter(opts ...RouterOption) (*CiscoGrpcClient, error) {
var router CiscoGrpcClient
for _, opt := range opts {
Expand Down Expand Up @@ -140,18 +141,6 @@ func newClientTLS(xr CiscoGrpcClient) (credentials.TransportCredentials, error)
skipVerify := true
xr.Domain = "ems.cisco.com"

// certPool := x509.NewCertPool()

// Add CA cert. FILE LOCATION CANNOT BE HARDCODED!!!!
/* file := "../input/certificate/ca.cert"
b, err := ioutil.ReadFile(file)
if err != nil {
return nil, fmt.Errorf("problem reading CA file %s: %s", file, err)
}
if !certPool.AppendCertsFromPEM(b) {
return nil, fmt.Errorf("failed to append CA certificate")
} */
config := &tls.Config{
// ServerName: xr.Domain,
InsecureSkipVerify: skipVerify,
Expand All @@ -174,10 +163,9 @@ func Connect(xr CiscoGrpcClient) (*grpc.ClientConn, context.Context, error) {
// Add TLS credentials to config options array.
opts = append(opts, grpc.WithTransportCredentials(creds))

// WithTimeout returns a DialOption that configures a timeout for dialing a ClientConn initially.
// This is valid if and only if WithBlock() is present
opts = append(opts, grpc.WithTimeout(time.Millisecond*time.Duration(2000)))
opts = append(opts, grpc.WithBlock())
// grpc.WithTimeout is deprecated
// opts = append(opts, grpc.WithTimeout(time.Millisecond*time.Duration(1500)))
// opts = append(opts, grpc.WithBlock())

// Add gRPC overall timeout to the config options array.
ctx, _ := context.WithTimeout(context.Background(), time.Second*time.Duration(xr.Timeout))
Expand All @@ -201,10 +189,9 @@ func ConnectInsecure(xr CiscoGrpcClient) (*grpc.ClientConn, context.Context, err
// opts holds the config options to set up the connection.
var opts []grpc.DialOption

// WithTimeout returns a DialOption that configures a timeout for dialing a ClientConn initially.
// This is valid if and only if WithBlock() is present
opts = append(opts, grpc.WithTimeout(time.Millisecond*time.Duration(1500)))
opts = append(opts, grpc.WithBlock())
// grpc.WithTimeout is deprecated
// opts = append(opts, grpc.WithTimeout(time.Millisecond*time.Duration(1500)))
// opts = append(opts, grpc.WithBlock())

// Add gRPC overall timeout to the config options array.
ctx, _ := context.WithTimeout(context.Background(), time.Second*time.Duration(xr.Timeout))
Expand All @@ -216,7 +203,7 @@ func ConnectInsecure(xr CiscoGrpcClient) (*grpc.ClientConn, context.Context, err
requireTLS: false}))

// Allow sending the credentials without TSL
opts = append(opts, grpc.WithInsecure())
opts = append(opts, grpc.WithTransportCredentials(insecure.NewCredentials()))

// conn represents a client connection to an RPC server (target).
conn, err := grpc.DialContext(ctx, xr.Host, opts...)
Expand All @@ -236,7 +223,7 @@ func ShowCmdTextOutput(ctx context.Context, conn *grpc.ClientConn, cli string, i
a := pb.ShowCmdArgs{ReqId: id, Cli: cli}

// 'st' is the streamed result that comes back from the target.
st, err := c.ShowCmdTextOutput(context.Background(), &a)
st, err := c.ShowCmdTextOutput(ctx, &a)
if err != nil {
return s, fmt.Errorf("gRPC ShowCmdTextOutput failed: %w", err)
}
Expand All @@ -257,37 +244,6 @@ func ShowCmdTextOutput(ctx context.Context, conn *grpc.ClientConn, cli string, i
}
}

// ActionJSON returns the output of an action commands as a JSON structured output.
// func ActionJSON(ctx context.Context, conn *grpc.ClientConn, j string, id int64) (string, error) {
// var s string
// // 'c' is the gRPC stub.
// c := pb.NewGRPCExecClient(conn)

// // 'a' is the object we send to the router via the stub.
// a := pb.ActionJSONArgs{ReqId: id, Yangpathjson: j}

// // 'st' is the streamed result that comes back from the target.
// st, err := c.ActionJSON(context.Background(), &a)
// if err != nil {
// return s, fmt.Errorf("gRPC ActionJSON failed: %w", err)
// }

// for {
// // Loop through the responses in the stream until there is nothing left.
// r, err := st.Recv()
// if err == io.EOF {
// return s, nil
// }
// if len(r.GetErrors()) != 0 {
// si := strconv.FormatInt(id, 10)
// return s, fmt.Errorf("error triggered by remote host for ReqId: %s; %s", si, r.GetErrors())
// }
// if len(r.GetYangjson()) > 0 {
// s += r.GetYangjson()
// }
// }
// }

// ShowCmdJSONOutput returns the output of a CLI show commands
// as a JSON structured output.
func ShowCmdJSONOutput(ctx context.Context, conn *grpc.ClientConn, cli string, id int64) (string, error) {
Expand All @@ -299,7 +255,7 @@ func ShowCmdJSONOutput(ctx context.Context, conn *grpc.ClientConn, cli string, i
a := pb.ShowCmdArgs{ReqId: id, Cli: cli}

// 'st' is the streamed result that comes back from the target.
st, err := c.ShowCmdJSONOutput(context.Background(), &a)
st, err := c.ShowCmdJSONOutput(ctx, &a)
if err != nil {
return s, fmt.Errorf("gRPC ShowCmdJSONOutput failed: %w", err)
}
Expand Down Expand Up @@ -331,7 +287,7 @@ func GetConfig(ctx context.Context, conn *grpc.ClientConn, js string, id int64)
a := pb.ConfigGetArgs{ReqId: id, Yangpathjson: js}

// 'st' is the streamed result that comes back from the target.
st, err := c.GetConfig(context.Background(), &a)
st, err := c.GetConfig(ctx, &a)
if err != nil {
return s, fmt.Errorf("gRPC GetConfig failed: %w", err)
}
Expand Down Expand Up @@ -385,7 +341,7 @@ func CommitConfig(ctx context.Context, conn *grpc.ClientConn, cm [2]string, id i
a := pb.CommitArgs{Msg: &m, ReqId: id}

// 'r' is the result that comes back from the target.
r, err := c.CommitConfig(context.Background(), &a)
r, err := c.CommitConfig(ctx, &a)
if err != nil {
return s, fmt.Errorf("gRPC CommitConfig failed: %w", err)
}
Expand All @@ -406,7 +362,7 @@ func CommitReplace(ctx context.Context, conn *grpc.ClientConn, cli, js string, i
a := pb.CommitReplaceArgs{Cli: cli, Yangjson: js, ReqId: id}

// 'r' is the result that comes back from the target.
r, err := c.CommitReplace(context.Background(), &a)
r, err := c.CommitReplace(ctx, &a)
if err != nil {
return fmt.Errorf("gRPC CommitReplace failed: %w", err)
}
Expand Down
10 changes: 6 additions & 4 deletions client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@
package xrgrpc_test

import (
"context"
"encoding/json"
"errors"
"fmt"
"net"
"strings"
"testing"
"time"
"errors"
"context"

xr "github.com/nleiva/xrgrpc"
pb "github.com/nleiva/xrgrpc/proto/ems"
Expand Down Expand Up @@ -40,7 +40,7 @@ const (
)

// execServer implements the GRPCExecServer interface
type execServer struct{pb.UnimplementedGRPCExecServer}
type execServer struct{ pb.UnimplementedGRPCExecServer }

func (s *execServer) ShowCmdTextOutput(a *pb.ShowCmdArgs, stream pb.GRPCExec_ShowCmdTextOutputServer) error {
if a.GetCli() != defaultCmd {
Expand Down Expand Up @@ -116,7 +116,9 @@ func (s *execServer) ShowCmdJSONOutput(a *pb.ShowCmdArgs, stream pb.GRPCExec_Sho
// }

// operConfigServer implements the GRPCConfigOperServer interface
type operConfigServer struct{pb.UnimplementedGRPCConfigOperServer}
type operConfigServer struct {
pb.UnimplementedGRPCConfigOperServer
}

func (s *operConfigServer) GetConfig(a *pb.ConfigGetArgs, stream pb.GRPCConfigOper_GetConfigServer) error {
if a.GetYangpathjson() != defaultYang {
Expand Down
4 changes: 2 additions & 2 deletions example/configvalidate/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ import (
"strings"
"time"

"google.golang.org/protobuf/proto"
xr "github.com/nleiva/xrgrpc"
"github.com/nleiva/xrgrpc/proto/telemetry"
bgp "github.com/nleiva/xrgrpc/proto/telemetry/bgp"
"google.golang.org/protobuf/proto"
)

// NeighborConfig uses asplain notation for AS numbers (RFC5396)
Expand Down Expand Up @@ -98,7 +98,7 @@ func main() {
id++
input := `{"openconfig-network-instance:network-instances":
{"network-instance":[{"name":"default","protocols":{"protocol":[{"bgp":{}}]}}]}}`

output, err := xr.GetConfig(ctx, conn, input, id)

if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion example/configvalidate4/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ import (
"strings"
"time"

"google.golang.org/protobuf/proto"
xr "github.com/nleiva/xrgrpc"
"github.com/nleiva/xrgrpc/proto/telemetry"
bgp "github.com/nleiva/xrgrpc/proto/telemetry/bgp4"
"google.golang.org/protobuf/proto"
)

// NeighborConfig uses asplain notation for AS numbers (RFC5396)
Expand Down
2 changes: 1 addition & 1 deletion example/configvalidateoc1/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ import (
"strings"
"time"

"google.golang.org/protobuf/proto"
xr "github.com/nleiva/xrgrpc"
"github.com/nleiva/xrgrpc/proto/telemetry"
"google.golang.org/protobuf/proto"
)

// NeighborConfig uses asplain notation for AS numbers (RFC5396)
Expand Down
2 changes: 1 addition & 1 deletion example/configvalidateoc2/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ import (
"os/signal"
"time"

"google.golang.org/protobuf/proto"
xr "github.com/nleiva/xrgrpc"
"github.com/nleiva/xrgrpc/proto/telemetry"
"google.golang.org/protobuf/proto"
)

// Colors, just for fun.
Expand Down
2 changes: 1 addition & 1 deletion example/configvalidateoc3/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ import (
"os/signal"
"time"

"google.golang.org/protobuf/proto"
xr "github.com/nleiva/xrgrpc"
"github.com/nleiva/xrgrpc/proto/telemetry"
"google.golang.org/protobuf/proto"
)

func main() {
Expand Down
2 changes: 1 addition & 1 deletion example/telemetry/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ import (
"os/signal"
"time"

proto "google.golang.org/protobuf/proto"
xr "github.com/nleiva/xrgrpc"
"github.com/nleiva/xrgrpc/proto/telemetry"
proto "google.golang.org/protobuf/proto"
)

func prettyprint(b []byte) ([]byte, error) {
Expand Down
2 changes: 1 addition & 1 deletion example/telemetrygpb/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ import (
"os/signal"
"time"

"google.golang.org/protobuf/proto"
xr "github.com/nleiva/xrgrpc"
"github.com/nleiva/xrgrpc/proto/telemetry"
lldp "github.com/nleiva/xrgrpc/proto/telemetry/lldp"
"google.golang.org/protobuf/proto"
)

func prettyprint(b []byte) ([]byte, error) {
Expand Down
Loading

0 comments on commit 69a348c

Please sign in to comment.