Skip to content
Snippets Groups Projects
client.go 5.19 KiB
Newer Older
  • Learn to ignore specific revisions
  • 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,
    	})
    
    // 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,
    	})
    
    // 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,
    	})
    
    // 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,
    	})
    
    // SchemaTree calls the SchemaTree method of the DeviceModelClients client. The
    // response stream is packed into a slice of bytes and returned.
    
    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
    }