Skip to content
Snippets Groups Projects
plugin.go 2.87 KiB
Newer Older
  • Learn to ignore specific revisions
  • 	"code.fbi.h-da.de/danet/gosdn/controller/customerrs"
    
    	"github.com/google/uuid"
    	"gopkg.in/yaml.v3"
    )
    
    // State represents the current state of a plugin within the controller. Since
    // the plugins used within the controller are basic go plugins, they can be
    // CREATED, BUILT, LOADED or FAULTY. A plugin can not be unloaded (this is a
    // limitation of go plugins in general).
    type State int64
    
    const (
    	//CREATED state describes a plugin which has been created but is not yet
    	//built.
    	CREATED State = iota
    	// BUILT state describes a plugin which is built and can be loaded into the
    	// controller.
    	BUILT
    	// LOADED state describes a plugin which is running within the controller.
    	LOADED
    	// FAULTY state describes a plugin which couldn't be built or loaded.
    	FAULTY
    )
    
    // Plugin describes an interface for a plugin within the controller - a plugin
    // in the context of the controller is a basic go plugin. A plugin satisfies
    // the Storable interface and can be stored.
    //
    // Note(mbauch): Currently a plugin is built through the controller itself.
    // This is fine for the time being, but should be reconsidered for the time to
    // come. In the future we should provide a build environment that allows to
    // build plugins within the same environment as the controller itself.
    type Plugin interface {
    	ID() uuid.UUID
    	State() State
    	Path() string
    	Manifest() *Manifest
    	Update() error
    }
    
    // Manifest represents the manifest of a plugin.
    type Manifest struct {
    	// Name of the plugin
    	Name string `yaml:"name"`
    	// Author of the plugin
    	Author string `yaml:"author"`
    	// Version of the plugin
    	Version string `yaml:"version"`
    }
    
    // Validate is a method to check if the manifest is valid and is compliant with
    // the requirements.
    func (m *Manifest) Validate() error {
    	errs := []error{}
    	if m.Name == "" {
    		errs = append(errs, fmt.Errorf("Name is required"))
    	}
    	if m.Author == "" {
    		errs = append(errs, fmt.Errorf("Author is required"))
    	}
    	if m.Version == "" {
    		errs = append(errs, fmt.Errorf("Version is required"))
    	}
    	// regex from: https://stackoverflow.com/a/68921827
    	validVersion, err := regexp.MatchString(`^v([1-9]\d*|0)(\.(([1-9]\d*)|0)){2}$`,
    		m.Version)
    	if err != nil {
    		errs = append(errs, err)
    	}
    	if !validVersion {
    		errs = append(errs, fmt.Errorf("Version has to be of form: vX.X.X"))
    	}
    	if len(errs) != 0 {
    
    		return customerrs.CombinedErrListError{Errors: errs}
    
    	}
    	return nil
    }
    
    // ReadManifestFromFile reads a manifest file and returns a pointer to a newly
    // created Manifest.
    func ReadManifestFromFile(path string) (*Manifest, error) {
    	manifest := &Manifest{}
    
    	manifestFile, err := ioutil.ReadFile(path)
    	if err != nil {
    		return nil, err
    	}
    	err = yaml.Unmarshal(manifestFile, manifest)
    	if err != nil {
    		return nil, err
    	}
    
    	// validate the loaded manifest
    	if err := manifest.Validate(); err != nil {
    		return nil, err
    	}
    
    	return manifest, nil
    }