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,
})
if err != nil {
return nil, err
}
return resp.GetNodes(), nil
}
// 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,
})
if err != nil {
return nil, err
}
return resp.Json, nil
}
// 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,
})
if err != nil {
return nil, err
}
return resp.GetNotification(), nil
}
// 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,
})
if err != nil {
return nil, err
}
return resp.GetModel(), nil
}
// 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,
})
if err != nil {
return nil, err
}
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.
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
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
}