ldk

package module
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 14, 2020 License: MIT Imports: 9 Imported by: 1

README

Loop Development Kit (LDK) for Go

The LDK is a plugin system for Sidekick. The LDK is built with go-plugin, a HashiCorp plugin system used in several of their projects.

Plugins developed with this library are executed by Sidekick as separate processes. This ensures that crashes or instability in the plugin will not destabilize the Sidekick process.

Communication between Sidekick and the plugin is first initialized over stdio and then performed using GRPC. On mac and linux the GRPC communication is sent over unix domain socket and on windows over local TCP socket.

In order for Sidekick to use a plugin, it must be compiled. Sidekick does not compile or interpret source code at runtime. A consequence of this is that plugins will need to be compiled for each operating system that they want to support.

Installation

go get -u github.com/open-olive/loop-development-kit-go

Terminology

Loop - A concept that describes how Intelligences, Sensors, and Controllers work together to provide useful information to the user.

Intelligence - A concept describing a source of information. This includes json files, databases, APIs, and more.

Sensor - A Sidekick plugin that emits events. For example, the clipboard sensor emits an event every time the clipboard contents change.

Controller - A Sidekick plugin that receives events from Sensors and emits whispers.

Whisper - A notification emitted by controllers and displayed in the Sidekick sidebar.

Sensor

A Sensor is a type of plugin that generates events. Events can be as simple as a chunk of text but allow for complicated information. Sensors do not choose which controllers get their events. They are simply emitting the events. The decision about which events to use is left to the controller.

Examples

These examples are currently private and only viewable by Olive employees.

Interface

Writing a Sensor plugin boils down to writing an implmentation for the Sensor interface.

type Sensor interface {
	Config() (Config, error)
	SetConfig(Config) error
	Start(SensorHost) error
	Stop() error
	OnEvent(Event) error
}

Config - The Sensor should return any configuration used by the plugin.

SetConfig - The Sensor should update the plugin configuration with the given values.

Start - The Sensor should wait to start operating until this is called. The provided SensorHost should be stored in memory for continued use.

Stop - The Sensor should stop operating when this is called.

OnEvent - The sensor can use this to handle events from the Sidekick UI. Many sensors will not care about UI events, and in that case the function should just return nil.

Sensor Lifecycle:
  1. Sidekick executes plugin process
  2. Sidekick calls Start, sending the host connection information to the plugin. This connection information is used to create the SensorHost. The SensorHost interface allows the plugin to emit events.
  3. On Sensor wanting to emit an event, the Sensor calls the EmitEvent method on the host interface.
  4. On Sidekick UI event, Sidekick calls OnEvent, passing the event to the Sensor. These events can be ignore or used at the Sensor's choice.
  5. On User disabling the Sensor, Sidekick calls Stop then sends sigterm to the process.
  6. On Sidekick shutdown, Sidekick calls Stop then sends sigterm to the process.

Controller

Controllers receive events and use them to generate relevant whispers. Controllers choose which events they want to use and which they want to ignore.

Examples

These examples are currently private and only viewable by Olive employees.

Interface

Writing a Controller plugin boils down to writing an implmentation for the Controller interface.

type Controller interface {
	Config() (map[string]string, error)
	SetConfig(map[string]string) error
	OnEvent(Event) error
	Start(ControllerHost) error
	Stop() error
}

Config - The Controller should return any configuration used by the plugin.

SetConfig - The Controller should update the plugin configuration with the given values.

Start - The Controller should wait to start operating until this is called. The provided ControllerHost should be stored in memory for continued use.

Stop - The Controller should stop operating when this is called.

OnEvent - The controller can use this to handle events that are broadcast by Sensors. Controllers do not need to emit events in a 1:1 relationship with events. Controllers may not use events at all. Controllers may only use some events. Controllers may keep a history of events and only emit whispers when several conditions are met.

Controller Lifecycle:
  1. Sidekick executes plugin process
  2. Sidekick calls Start, sending the host connection information to the plugin. This connection information is used to create the ControllerHost. The ControllerHost interface allows the plugin to emit whispers.
  3. On Controller wanting to emit a whisper, the Controller calls the EmitWhisper method on the host interface.
  4. On Sensor event, Sidekick calls OnEvent, passing the event from the Sensor to the Controllelr. These events can be ignore or used at the Controllers's choice.
  5. On User disabling the Controller, Sidekick calls Stop then sends sigterm to the process.
  6. On Sidekick shutdown, Sidekick calls Stop then sends sigterm to thse process.

Documentation

Index

Constants

View Source
const (
	// CategoryUnknown is the category used when the category is not known
	CategoryUnknown = iota

	// CategoryIntelligence is the category used by intelligences
	CategoryIntelligence

	// CategoryController is the category used by controllers
	CategoryController

	// CategorySensor is the category used by sensors
	CategorySensor

	// CategorySidekick is the category used by the main sidekick process
	CategorySidekick
)

Variables

View Source
var ControllerPluginMap = map[string]plugin.Plugin{
	"controller": &ControllerGRPCPPlugin{},
}

ControllerPluginMap is the map of plugins we can dispense.

View Source
var Handshake = plugin.HandshakeConfig{
	ProtocolVersion:  1,
	MagicCookieKey:   "BASIC_PLUGIN",
	MagicCookieValue: "hello",
}

Handshake is a collection of information used to initialize communication between plugin and hosot

View Source
var SensorPluginMap = map[string]plugin.Plugin{
	"sensor": &SensorGRPCPPlugin{},
}

SensorPluginMap is the map of plugins we can dispense.

Functions

func IsInstallMode

func IsInstallMode() bool

IsInstallMode determines if the plugin is executed in a way meant to be for installation

func IsUninstallMode

func IsUninstallMode() bool

IsUninstallMode determines if the plugin is executed in a way meant to be for uninstallation

Types

type Category

type Category int

Category is a grouping of entity type

func (Category) MarshalJSON

func (c Category) MarshalJSON() ([]byte, error)

MarshalJSON returns a json serialization of the category

func (Category) MarshalYAML

func (c Category) MarshalYAML() (interface{}, error)

MarshalYAML returns a yaml serialization of the category

func (Category) String

func (c Category) String() string

func (*Category) UnmarshalJSON

func (c *Category) UnmarshalJSON(b []byte) error

UnmarshalJSON sets the category from the json data

func (*Category) UnmarshalYAML

func (c *Category) UnmarshalYAML(unmarshal func(interface{}) error) error

UnmarshalYAML sets the category from the yaml data

type Config

type Config map[string]string

Config is a type used to store the configuration parameters of a plugin

type Controller

type Controller interface {
	Config() (map[string]string, error)
	SetConfig(map[string]string) error
	OnEvent(Event) error
	Start(ControllerHost) error
	Stop() error
}

Controller is an interface that defines the methods required of all controller plugins

type ControllerGRPCClient

type ControllerGRPCClient struct {
	Metadata Metadata
	// contains filtered or unexported fields
}

ControllerGRPCClient is used by the controller plugin host to facilitate host initiated communication with controller plugins

func (*ControllerGRPCClient) Config

func (m *ControllerGRPCClient) Config() (map[string]string, error)

Config is called by the host to retrieve the configuration of the plugin

func (*ControllerGRPCClient) OnEvent

func (m *ControllerGRPCClient) OnEvent(event Event) error

OnEvent is called by the host to send an event to the controller

func (*ControllerGRPCClient) SetConfig

func (m *ControllerGRPCClient) SetConfig(config map[string]string) error

SetConfig is called by the host to set the configuration of the plugin

func (*ControllerGRPCClient) Start

func (m *ControllerGRPCClient) Start(host ControllerHost) error

Start is called by the host when the plugin is started to provide access to the host process

func (*ControllerGRPCClient) Stop

func (m *ControllerGRPCClient) Stop() error

Stop is called by the host when the plugin is stopped

type ControllerGRPCHostClient

type ControllerGRPCHostClient struct {
	// contains filtered or unexported fields
}

ControllerGRPCHostClient is used by the controller plugin to facilitate plugin initiated communication with the host

func (*ControllerGRPCHostClient) EmitWhisper

func (m *ControllerGRPCHostClient) EmitWhisper(whisper Whisper) error

EmitWhisper is used by controller plugins to send whispers to sidekick

type ControllerGRPCHostServer

type ControllerGRPCHostServer struct {
	// This is the real implementation
	Impl ControllerHost

	Metadata Metadata
}

ControllerGRPCHostServer is used by the controller plugin host to receive plugin initiated communication

func (*ControllerGRPCHostServer) EmitWhisper

EmitWhisper is used by controller plugins to send whispers to sidekick

type ControllerGRPCPPlugin

type ControllerGRPCPPlugin struct {
	plugin.NetRPCUnsupportedPlugin
	Impl Controller
}

ControllerGRPCPPlugin is a structure used to define the parameters of the plugin communication

func (*ControllerGRPCPPlugin) GRPCClient

func (p *ControllerGRPCPPlugin) GRPCClient(ctx context.Context, broker *plugin.GRPCBroker, c *grpc.ClientConn) (interface{}, error)

GRPCClient is used to generate controller clients that can be used by the host

func (*ControllerGRPCPPlugin) GRPCServer

func (p *ControllerGRPCPPlugin) GRPCServer(broker *plugin.GRPCBroker, s *grpc.Server) error

GRPCServer is used to register the controller plugin with the GRPC server

type ControllerGRPCServer

type ControllerGRPCServer struct {
	Impl Controller
	// contains filtered or unexported fields
}

ControllerGRPCServer is used by the controller plugin to receive host initiated communication

func (*ControllerGRPCServer) Config

Config is called by the host to retrieve the configuration of the plugin

func (*ControllerGRPCServer) OnEvent

OnEvent is called by the host to send an event to the plugin

func (*ControllerGRPCServer) SetConfig

SetConfig is called by the host to set the configuration of the plugin

func (*ControllerGRPCServer) Start

Start is called by the host when the plugin is started to provide access to the host process

func (*ControllerGRPCServer) Stop

Stop is called by the host when the plugin is stopped

type ControllerHost

type ControllerHost interface {
	EmitWhisper(Whisper) error
}

ControllerHost is an interface that defines what methods plugins can expect from the host

type Event

type Event struct {
	Source Source            `json:"source"`
	Data   map[string]string `json:"data"`
}

Event is a structure that defines a sensor event

func NewTextEvent

func NewTextEvent(text string) Event

NewTextEvent generates a new event with the given text

func (*Event) Text

func (e *Event) Text() string

Text is a shortcut for returning Event.Data["text"]

type Metadata

type Metadata struct {
	// Author is the creator of the entity
	Author string `json:"author" yaml:"author"`

	// Category is a grouping of entity type
	// Ex: "intelligence", "loop", "sensor"
	Category Category `json:"category" yaml:"category"`

	// Created is the time when the entity was created
	Created time.Time `json:"created" yaml:"created"`

	// Description is a short explaintion of the entity
	Description string `json:"description" yaml:"description"`

	// ID is a unique identifier for this entity
	ID string `json:"id" yaml:"id"`

	// Icon is a URL for an icon representing this entity
	Icon string `json:"icon" yaml:"icon"`

	// Name is a human readable identifier for this entity
	Name string `json:"name" yaml:"name"`

	// Organization is the name of the organization to which the Author belongs
	Organization string `json:"organization" yaml:"organization"`

	// Specification is a string indication which version
	// of the specification is being used to describe this entity
	Specification string `json:"specification" yaml:"specification"`

	// Updated is the time when the entity was last updated
	Updated time.Time `json:"updated" yaml:"updated"`

	// Version is a semver version of this entity
	Version string `json:"version" yaml:"version"`
}

Metadata is data about an entity

type Sensor

type Sensor interface {
	Config() (Config, error)
	SetConfig(Config) error
	Start(SensorHost) error
	Stop() error
	OnEvent(Event) error
}

Sensor is an interface that defines the methods required of all sensor plugins

type SensorGRPCClient

type SensorGRPCClient struct {
	Metadata Metadata
	// contains filtered or unexported fields
}

SensorGRPCClient is used by the sensor plugin host to facilitate host initiated communication with sensor plugins

func (*SensorGRPCClient) Config

func (m *SensorGRPCClient) Config() (Config, error)

Config is called by the host to retrieve the configuration of the plugin

func (*SensorGRPCClient) OnEvent

func (m *SensorGRPCClient) OnEvent(event Event) error

OnEvent is called by the host to send an event to the sensor

func (*SensorGRPCClient) SetConfig

func (m *SensorGRPCClient) SetConfig(config Config) error

SetConfig is called by the host to set the configuration of the plugin

func (*SensorGRPCClient) Start

func (m *SensorGRPCClient) Start(host SensorHost) error

Start is called by the host when the plugin is started to provide access to the host process

func (*SensorGRPCClient) Stop

func (m *SensorGRPCClient) Stop() error

Stop is called by the host when the plugin is stopped

type SensorGRPCHostClient

type SensorGRPCHostClient struct {
	// contains filtered or unexported fields
}

SensorGRPCHostClient is used by the sensor plugin to facilitate plugin initiated communication with the host

func (*SensorGRPCHostClient) EmitEvent

func (m *SensorGRPCHostClient) EmitEvent(event Event) error

EmitEvent is used by sensor plugins to send events to the host

type SensorGRPCHostServer

type SensorGRPCHostServer struct {
	// This is the real implementation
	Impl SensorHost

	Metadata Metadata
}

SensorGRPCHostServer is used by the sensor plugin host to receive plugin initiated communication

func (*SensorGRPCHostServer) EmitEvent

EmitEvent is used by sensor plugins to send events to the host

type SensorGRPCPPlugin

type SensorGRPCPPlugin struct {
	plugin.NetRPCUnsupportedPlugin
	Impl Sensor
}

SensorGRPCPPlugin is a structure used to define the parameters of the plugin communication

func (*SensorGRPCPPlugin) GRPCClient

func (p *SensorGRPCPPlugin) GRPCClient(ctx context.Context, broker *plugin.GRPCBroker, c *grpc.ClientConn) (interface{}, error)

GRPCClient is used to generate sensor clients that can be used by the host

func (*SensorGRPCPPlugin) GRPCServer

func (p *SensorGRPCPPlugin) GRPCServer(broker *plugin.GRPCBroker, s *grpc.Server) error

GRPCServer is used to register the sensor plugin with the GRPC server

type SensorGRPCServer

type SensorGRPCServer struct {
	Impl Sensor
	// contains filtered or unexported fields
}

SensorGRPCServer is used by the sensor plugin to receive host initiated communication

func (*SensorGRPCServer) Config

Config is called by the host to retrieve the configuration of the plugin

func (*SensorGRPCServer) OnEvent

OnEvent is called by the host to send an event to the plugin

func (*SensorGRPCServer) SetConfig

func (m *SensorGRPCServer) SetConfig(ctx context.Context, req *proto.SetConfigRequest) (*proto.Empty, error)

SetConfig is called by the host to set the configuration of the plugin

func (*SensorGRPCServer) Start

Start is called by the host when the plugin is started to provide access to the host process

func (*SensorGRPCServer) Stop

func (m *SensorGRPCServer) Stop(ctx context.Context, req *proto.Empty) (*proto.Empty, error)

Stop is called by the host when the plugin is stopped

type SensorHost

type SensorHost interface {
	EmitEvent(Event) error
}

SensorHost is an interface that defines what methods plugins can expect from the host

type Source

type Source struct {
	// Author is the creator of the entity
	Author string `json:"author" yaml:"author"`

	// Category is a grouping of entity type
	// Ex: "intelligence", "loop", "sensor"
	Category Category `json:"category" yaml:"category"`

	// ID is a unique identifier for this entity
	ID string `json:"id" yaml:"id"`

	// Name is a human readable identifier for this entity
	Name string `json:"name" yaml:"name"`

	// Organization is the name of the organization to which the Author belongs
	Organization string `json:"organization" yaml:"organization"`

	// Version is a semver version of this entity
	Version string `json:"version" yaml:"version"`
}

Source is information about the origin of the data

type Style

type Style struct {
	BackgroundColor string `json:"backgroundColor"`
	HighlightColor  string `json:"highlightColor"`
	PrimaryColor    string `json:"primaryColor"`
}

Style contains fields for specifying whisper style

type Whisper

type Whisper struct {
	Markdown  string    `json:"markdown"`
	CreatedAt time.Time `json:"createdAt"`
	ID        string    `json:"id"`
	Icon      string    `json:"icon"` // Material Icon name https://material.io/resources/icons/
	Label     string    `json:"label"`
	Style     Style     `json:"style"`
	Source    Source    `json:"source"`
}

Whisper is the information output of a loop

func NewWhisper

func NewWhisper(markdown string, label string, icon string, style Style) (Whisper, error)

NewWhisper creates a new Whisper struct with a random ID

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL