service

package
v1.5.6 Latest Latest
Warning

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

Go to latest
Published: Apr 28, 2023 License: MIT Imports: 16 Imported by: 6

Documentation

Overview

Package plugin/service provides a common way for host and plugins to communicate in a IPC-like way.

In this framework, the host serves as the server while the plugins serves as clients. The plugins requests services provided by server through namespace, name and arguments. To simplify the problem, all data will be marshaled and transferred in json.

The host-plugin communication will be multiplexed over a pair of pipes which are identified by URLs. The scheme of the URL identifies the kind of opener it is, while the host and path portion specifies how to reach the file. And the communiction pipes can be named pipes, sockets and even shared memories, as long as valid opener is defined for it.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AddHostFlags

func AddHostFlags(flag *pflag.FlagSet)

AddHostFlags attempts to add flags for opening host file.

func GetManifest

func GetManifest(namespace string, v interface{}) error

GetManifest attempt to retrieve manifest for namespace.

func GetService

func GetService(namespace, name string, service Service)

GetService will attempt to retrieve a service from host.

The service argument must be a pointer to function, and a common usage for it might be shown as below:

var target func(x, y int) (z int, err error)
plugin.GetService("my-package", "add", &target)
target(1, 2) // returns (3, nil) on success

This function panics when the provided service argument is not acceptable. While other errors should be returned as the error in provided function.

func HasNamespace

func HasNamespace(namespace string) (bool, error)

HasNamespace attempt to verify whether namespace exists.

func Hosted

func Hosted() bool

Hosted returns whether current process is hosted.

With this argument, each plugin process can choose to write to the standard output directly if it is not hosted, or to communicate with the host process for output write back.

func InitServiceClient

func InitServiceClient(ctx context.Context) error

InitServiceClient attempts to initialize the service client when it is executed from a plugin.

Though it is dispensible, it is the only chance for setting up context for service client, so it should be executed before any service has been called.

func ListServices

func ListServices(namespace string) ([]string, error)

ListServices attempt to list services in a namespace.

func RegisterFileOpener

func RegisterFileOpener(scheme string, f FileOpener)

RegisterFileOpener registers the opener of file with scheme.

func WithFilePath

func WithFilePath(p string) plugin.ExecOption

WithFilePath is used when the input and output stream can be open by directly opening file with filepath.

func WithFilePathPair

func WithFilePathPair(input, output string) plugin.ExecOption

WithFilePathPair is just like WithFilePath but is used when the input and output stream should use different files.

Types

type BindFunc

type BindFunc func(
	ctx context.Context, plug *plugin.Plugin, cmd *plugin.Command,
	reader io.ReadCloser, writer io.WriteCloser,
	next func(context.Context, ...plugin.ExecOption) error,
) error

BindFunc binds running service to specified file.

When bind function is called, the server corresponding to specified registry is already running. And bind function should create communication pipes, redirect input and output of the pipes to the stream provided by the server, and finally invoke the next function to go on.

type BindOption

type BindOption func(*bindOption)

BindOption is the option that could be use when bind.

func WithAnonymousPipe

func WithAnonymousPipe() BindOption

WithAnonymousPipe presumes the procfs is located on /proc, which is equivalent to service.WithAnonymousPipeByProcFS("/proc").

func WithAnonymousPipeByProcFS

func WithAnonymousPipeByProcFS(procfs string) BindOption

WithAnonymousPipeByProcFS attempt to create a pair of anonymous pipes in host process, and tell plugin processes to open pipes by visiting procfs mounted on specified path.

This is the default option on linux, assuming the host and plugins are running inside the same process. However you cannot use this flag directly when the plugin is to be executed inside a container with CLONE_NEWPID set.

func WithBindFunc

func WithBindFunc(f BindFunc) BindOption

type FileOpener

type FileOpener func(url *url.URL, flag int) (io.ReadWriteCloser, error)

FileOpener specifies the opener of host communication file.

type Registry

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

Registry records the marshaled services that will be provided to the plugins.

func NewRegistry

func NewRegistry() *Registry

NewRegistry creates a root registry object.

func (*Registry) AddService

func (r *Registry) AddService(ns, name string, svc Service)

AddService attempt to add the service to namespace.

The namespace must be defined in current registry, which means the caller cannot modifies namespaces in the parent layer of current registry.

func (*Registry) AddServices

func (r *Registry) AddServices(svcs Services)

AddServices attempt to add the services to the registry.

func (*Registry) Bind

func (r *Registry) Bind(opts ...BindOption) plugin.ExecOption

Bind the registry into a running service.

func (*Registry) Define

func (r *Registry) Define(ns string, manifest interface{})

Define a new namespace in the current registry.

func (*Registry) Inherit

func (r *Registry) Inherit() *Registry

Inherit attempt to inherit and add their own services.

type Service

type Service interface{}

Service is service function's general interface.

Each service will be a function with multiple arguments and results. While running, the arguments will be attempted to be marshaled into json, while the results will be marshaled from json.

There's a special restriction that the service provider should not use error interface as one of the arguments or results, while the service consumer must have the error interface as the last argument to receive interface error.

Say, we have a service whose prototype looks like func(A, B) C, and thus its service consumer must be in the form of func(A, B) (C, error).

type Services

type Services interface {
	Add(*Registry)
}

Services inverse the control of registering operations and simplifies the interface provided to user.

Jump to

Keyboard shortcuts

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