Skip to content
Snippets Groups Projects
plugin.go 5.22 KiB
Newer Older
  • Learn to ignore specific revisions
  • 	"code.fbi.h-da.de/danet/gosdn/controller/customerrs"
    
    	"code.fbi.h-da.de/danet/gosdn/controller/interfaces/plugin"
    
    	"code.fbi.h-da.de/danet/gosdn/controller/nucleus/util"
    
    	"code.fbi.h-da.de/danet/gosdn/controller/plugin/shared"
    	"github.com/google/uuid"
    	hcplugin "github.com/hashicorp/go-plugin"
    	"go.mongodb.org/mongo-driver/bson"
    
    type Plugin struct {
    	UUID     uuid.UUID
    	state    plugin.State
    
    	manifest *plugin.Manifest
    	client   *hcplugin.Client
    	shared.DeviceModel
    }
    
    
    func NewPlugin(id uuid.UUID, execPath string) (*Plugin, error) {
    
    	client := hcplugin.NewClient(&hcplugin.ClientConfig{
    		HandshakeConfig:  shared.Handshake,
    		Plugins:          shared.PluginMap,
    
    		Cmd:              exec.Command("sh", "-c", filepath.Join(execPath, util.PluginExecutableName)),
    
    		AllowedProtocols: []hcplugin.Protocol{hcplugin.ProtocolGRPC},
    	})
    
    
    	manifest, err := plugin.ReadManifestFromFile(execPath)
    
    
    	// connect through grpc
    	gRPCClient, err := client.Client()
    
    
    	// Request the plugin
    	raw, err := gRPCClient.Dispense("deviceModel")
    
    	model, ok := raw.(shared.DeviceModel)
    	if !ok {
    		return nil, customerrs.InvalidTypeAssertionError{
    			Value: raw,
    			Type:  (*shared.DeviceModel)(nil),
    		}
    	}
    
    	return &Plugin{
    		UUID:        id,
    		client:      client,
    
    		DeviceModel: model,
    		manifest:    manifest,
    		state:       plugin.CREATED,
    	}, nil
    
    func NewPluginThroughReattachConfig(loadedPlugin plugin.LoadedPlugin) (plugin.Plugin, error) {
    	client := hcplugin.NewClient(&hcplugin.ClientConfig{
    		HandshakeConfig:  shared.Handshake,
    		Plugins:          shared.PluginMap,
    		Reattach:         &loadedPlugin.ReattachConfig,
    		AllowedProtocols: []hcplugin.Protocol{hcplugin.ProtocolGRPC},
    	})
    
    	// connect through grpc
    	gRPCClient, err := client.Client()
    	if err != nil {
    		return nil, err
    	}
    
    	// Request the plugin
    	raw, err := gRPCClient.Dispense("deviceModel")
    
    	model, ok := raw.(shared.DeviceModel)
    	if !ok {
    		return nil, customerrs.InvalidTypeAssertionError{
    			Value: model,
    			Type:  (*shared.DeviceModel)(nil),
    
    
    	return &Plugin{
    		UUID:        uuid.MustParse(loadedPlugin.ID),
    		client:      client,
    		DeviceModel: model,
    		manifest:    &loadedPlugin.Manifest,
    		state:       plugin.CREATED,
    	}, nil
    }
    
    // ID returns the ID of the plugin.
    func (p *Plugin) ID() uuid.UUID {
    	return p.UUID
    }
    
    // ID returns the ID of the plugin.
    func (p *Plugin) ReattachConfig() *hcplugin.ReattachConfig {
    	return p.client.ReattachConfig()
    }
    
    // State returns the current state of the plugin.
    // Different states of the plugin can be:
    //   - built
    //   - loaded
    //   - faulty
    func (p *Plugin) State() plugin.State {
    	return p.state
    }
    
    
    func (p *Plugin) ExecPath() string {
    	return p.execPath
    
    }
    
    // GetClient returns the client of the plugin.
    func (p *Plugin) GetClient() *hcplugin.Client {
    	return p.client
    }
    
    // Manifest returns the manifest of the plugin.
    func (p *Plugin) Manifest() *plugin.Manifest {
    	return p.manifest
    }
    
    func (p *Plugin) Update() error {
    	return fmt.Errorf("not implemented yet")
    }
    
    func (p *Plugin) Restart() error {
    	return fmt.Errorf("not implemented yet")
    }
    
    // Close ends the execution of the plugin.
    func (p *Plugin) Close() {
    	p.client.Kill()
    }
    
    // Ping checks if the client connection is healthy.
    func (p *Plugin) Ping() error {
    	protocolClient, err := p.client.Client()
    	if err != nil {
    		return err
    
    	return protocolClient.Ping()
    }
    
    // TODO: update for the new way of handling plugins
    // UpdatePlugin updates a given Plugin. Therefore the version of the
    // `plugin.yml` manifest file is compared to the version in use. If a new
    // version is within the plugin folder, the new version of the plugin is built.
    func UpdatePlugin(p plugin.Plugin) (updated bool, err error) {
    	return false, fmt.Errorf("not implemented yet")
    }
    
    func (p *Plugin) MarshalJSON() ([]byte, error) {
    	return json.Marshal(&struct {
    		ID             uuid.UUID                `json:"id,omitempty"`
    		Manifest       *plugin.Manifest         `json:"manifest" bson:"manifest"`
    		State          plugin.State             `json:"state,omitempty" bson:"state"`
    
    		ExecPath       string                   `json:"exec_path,omitempty" bson:"exec_path"`
    
    		ReattachConfig *hcplugin.ReattachConfig `json:"reattatch_config,omitempty" bson:"reattatch_config"`
    	}{
    		ID:             p.ID(),
    		Manifest:       p.Manifest(),
    		State:          p.State(),
    
    		ReattachConfig: p.ReattachConfig(),
    	})
    }
    
    func (p *Plugin) MarshalBSON() ([]byte, error) {
    	return bson.Marshal(&struct {
    		ID             string                   `bson:"_id,omitempty"`
    		Manifest       *plugin.Manifest         `json:"manifest" bson:"manifest"`
    		State          plugin.State             `json:"state,omitempty" bson:"state"`
    
    		ExecPath       string                   `json:"exec_path,omitempty" bson:"exec_path"`
    
    		ReattachConfig *hcplugin.ReattachConfig `json:"reattatch_config,omitempty" bson:"reattatch_config"`
    	}{
    		ID:             p.ID().String(),
    		Manifest:       p.Manifest(),
    		State:          p.State(),