Newer
Older
package shared
import (
"errors"
"io"
"golang.org/x/net/context"
mnepb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/networkelement"
pb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/plugin"
gpb "github.com/openconfig/gnmi/proto/gnmi"
"github.com/sirupsen/logrus"
)
// DeviceModelClient is the implementation of a DeviceModel that can
// communicate via gRPC. The main purpose it to act as the gRPC client for the
// DeviceModelPlugin. A hashicorp client can consume and use it. The
// DeviceModelClient has to satisfy the DeviceModel interface and therefore
// implements all the needed methods.
type DeviceModelClient struct{ client pb.PluginClient }
// Unmarshal calls the Unmarshal method of the DeviceModelClients client. A
// request is created with the given json and path. If the operation failed an
// error is returned.
func (m *DeviceModelClient) Unmarshal(json []byte, path *gpb.Path) error {
_, err := m.client.Unmarshal(context.Background(), &pb.UnmarshalRequest{
Json: json,
Path: path,
})
return err
}
// SetNode calls the SetNode method of the DeviceModelClients client. A request
// is created with the given path and value. If the operation failed an error is
// returned.
func (m *DeviceModelClient) SetNode(path *gpb.Path, value *gpb.TypedValue) error {
_, err := m.client.SetNode(context.Background(), &pb.SetNodeRequest{
Path: path,
Value: value,
})
return err
}
// GetNode calls the GetNode method of the DeviceModelClients client. A request
// is created with the given path and the provided boolean that decides if only
// the intended state should be requested. The response is returned as a slice
// of notifications. If the operation failed an error is returned.
func (m *DeviceModelClient) GetNode(path *gpb.Path, requestForIntendedState bool) ([]*gpb.Notification, error) {
resp, err := m.client.GetNode(context.Background(), &pb.GetNodeRequest{
Path: path,
RequestForIntendedState: requestForIntendedState,
})
return resp.GetNodes(), err
}
// DeleteNode calls the DeleteNode method of the DeviceModelClients client. A
// request is created with the given path. If the operation failed an error is
// returned.
func (m *DeviceModelClient) DeleteNode(path *gpb.Path) error {
_, err := m.client.DeleteNode(context.Background(), &pb.DeleteNodeRequest{
Path: path,
})
return err
}
// Model calls the Model method of the DeviceModelClients client. A request is
// created with the given boolean that decides if read-only nodes should be
// filtered. The response returns the model (filtered or not) as json. If the
// operation failed an error is returned.
func (m *DeviceModelClient) Model(filterReadOnly bool) ([]byte, error) {
resp, err := m.client.Model(context.Background(), &pb.ModelRequest{
FilterReadOnly: filterReadOnly,
})
return resp.Json, err
}
// Diff calls the Diff method of the DeviceModelClients client. A request is
// created with the given original and modified model. The response returns the
// diff as a gnmi notifications. If the operation failed an error is returned.
func (m *DeviceModelClient) Diff(original, modified []byte) (*gpb.Notification, error) {
resp, err := m.client.Diff(context.Background(), &pb.DiffRequest{
Original: original,
Modified: modified,
})
return resp.GetNotification(), err
}
// ValidateChange calls the ValidateChange method of the DeviceModelClients
// client. A request is created with the given operation, path and value (as
// gnmi.TypedValue). The response returns the model as json. If the operation
// failed an error is returned.
func (m *DeviceModelClient) ValidateChange(operation mnepb.ApiOperation, path *gpb.Path, value *gpb.TypedValue) ([]byte, error) {
resp, err := m.client.ValidateChange(context.Background(), &pb.ValidateChangeRequest{
Operation: operation,
Path: path,
Value: value,
})
return resp.GetModel(), err
}
// PruneConfigFalse calls the PruneConfigFalse method of the DeviceModelClients
// client. A request is created with the given model value (json as byte[]).
// The response returns the model with the pruned config false nodes. If the
// operation failed an error is returned.
func (m *DeviceModelClient) PruneConfigFalse(value []byte) ([]byte, error) {
resp, err := m.client.PruneConfigFalse(context.Background(), &pb.PruneConfigFalseRequest{
Value: value,
})
return resp.GetModel(), err
}
// SchemaTree calls the SchemaTree method of the DeviceModelClients client. The
// response stream is packed into a slice of bytes and returned.
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
func (m *DeviceModelClient) SchemaTreeGzip() ([]byte, error) {
schemaTreeGzipClient, err := m.client.SchemaTreeGzip(context.Background(), &pb.SchemaTreeGzipRequest{})
if err != nil {
return nil, err
}
sTreeBytes := []byte{}
for {
payload, err := schemaTreeGzipClient.Recv()
if err != nil {
if errors.Is(err, io.EOF) {
break
}
logrus.Error(err)
closeErr := schemaTreeGzipClient.CloseSend()
if closeErr != nil {
return nil, err
}
return nil, err
}
sTreeBytes = append(sTreeBytes, payload.Chunk...)
}
return sTreeBytes, nil
}