plugin

package
v0.0.0-...-2bc12df Latest Latest
Warning

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

Go to latest
Published: Mar 18, 2021 License: Apache-2.0 Imports: 19 Imported by: 0

Documentation

Overview

Package plugin defines a set of interfaces that plugins must implement to enable wash functonality.

All resources must implement the Entry interface. To do so they should include the EntryBase type, and initialize it via NewEntry. For example

type myResource struct {
	plugin.EntryBase
}
...
rsc := myResource{plugin.NewEntry("a resource")}

EntryBase gives the resource a name - which is how it will be displayed in the filesystem or referenced via the API - and tools for controlling how its data is cached.

Implementing the Parent interface displays that resource as a directory on the filesystem. Anything that does not implement Parent will be displayed as a file.

The Readable interface allows reading data from an entry via the filesystem. The Writable interface allows sending data to the entry.

Wash distinguishes between two different patterns for things you can read and write. It considers a "file-like" entry to be one with a defined size (so the `size` attribute is set when listing the entry). Reading and writing a "file-like" entry edits the contents. Something that can be read and written but doesn't define size has different characteristics. Reading and writing are not symmetrical: if you write to it then read from it, you may not see what you just wrote. So these non-file-like entries error if you try to open them with a ReadWrite handle. If your plugin implements non-file-like write-semantics, remember to document how they work in the plugin schema's description.

All of the above, as well as other types - Execable, Stream - provide additional functionality via the HTTP API.

Index

Constants

View Source
const (
	// ListOp represents Parent#List
	ListOp defaultOpCode = iota
	// ReadOp represents Readable/BlockReadable#Read
	ReadOp
	// MetadataOp represents Entry#Metadata
	MetadataOp
)

Variables

View Source
var DefaultTimeout = 10 * time.Second

DefaultTimeout is the default timeout for prefetching

Functions

func Actions

func Actions() map[string]Action

Actions returns all of the available Wash actions as a map of <action_name> => <action_object>.

func CName

func CName(e Entry) string

CName returns the entry's canonical name, which is what Wash uses to construct the entry's path. The entry's cname is plugin.Name(e), but with all '/' characters replaced by a '#' character. CNames are necessary because it is possible for entry names to have '/'es in them, which is illegal in bourne shells and UNIX-y filesystems.

CNames are unique. CName uniqueness is checked in plugin.CachedList.

NOTE: The '#' character was chosen because it is unlikely to appear in a meaningful entry's name. If, however, there's a good chance that an entry's name can contain the '#' character, and that two entries can have the same cname (e.g. 'foo/bar', 'foo#bar'), then you can use e.SetSlashReplacer(<char>) to change the default slash replacer from a '#' to <char>.

func CachedOp

func CachedOp(ctx context.Context, opName string, entry Entry, ttl time.Duration, op opFunc) (interface{}, error)

CachedOp caches the given op's result for the duration specified by the ttl. You should use it when you need more fine-grained caching than what the existing CachedList, CachedOpen, and CachedMetadata methods provide. For example, CachedOp could be useful to cache an API request whose response lets you implement Open() and Metadata() for the given entry.

A ttl of 0 uses the cache default of 1 minute. Negative ttls are not allowed.

CachedOp uses the supplied context to determine where to log activity.

func ClearCacheFor

func ClearCacheFor(path string, clearAncestorList bool) []string

ClearCacheFor removes entries from the cache that match or are children of the provided path. If successful, returns an array of deleted keys. Optionally clear the list operation for the parent to remove any attributes related to the specified entry.

TODO: If path == "/", we could optimize this by calling cache.Flush(). Not important right now, but may be worth considering in the future.

func Delete

func Delete(ctx context.Context, d Deletable) (deleted bool, err error)

Delete deletes the given entry.

func DeleteWithAnalytics

func DeleteWithAnalytics(ctx context.Context, d Deletable) (bool, error)

DeleteWithAnalytics is a wrapper to plugin.Delete. Use it when you need to report a 'Delete' invocation to analytics. Otherwise, use plugin.Delete.

func ID

func ID(e Entry) string

ID returns the entry's ID, which is just its path rooted at Wash's mountpoint. An entry's ID is described as

/<plugin_name>/<parent1_cname>/<parent2_cname>/.../<entry_cname>

NOTE: <plugin_name> is really <plugin_cname>. However since <plugin_name> can never contain a '/', <plugin_cname> reduces to <plugin_name>.

func InitCache

func InitCache()

InitCache initializes the cache

func InitInteractive

func InitInteractive(init bool)

InitInteractive is used by Wash commands to set option-specific overrides. Only sets interactivity to true if it already was and 'init' is also true.

func IsInteractive

func IsInteractive() bool

IsInteractive returns true if Wash is running as an interactive session. If false, please don't prompt for input on stdin.

func IsInvalidInputErr

func IsInvalidInputErr(err error) bool

IsInvalidInputErr returns true if err is an InvalidInputErr error object

func IsPrefetched

func IsPrefetched(e Entry) bool

IsPrefetched returns whether an entry has data that was added during creation that it would like to have updated.

func Name

func Name(e Entry) string

Name returns the entry's name as it was passed into plugin.NewEntry. It is meant to be called by other Wash packages. Plugin authors should use EntryBase#Name when writing their plugins.

func Prompt

func Prompt(msg string) (string, error)

Prompt prints the supplied message, then waits for input on stdin.

func Read

func Read(ctx context.Context, e Entry, size int64, offset int64) (data []byte, err error)

Read reads up to size bits of the entry's content starting at the given offset. It will panic if the entry does not support the read action. Callers can use len(data) to check the amount of data that was actually read.

If the offset is >= to the available content size, then data != nil, len(data) == 0, and err == io.EOF. Otherwise if len(data) < size, then err == io.EOF.

Note that Read is thread-safe.

func ReadWithAnalytics

func ReadWithAnalytics(ctx context.Context, e Entry, size int64, offset int64) ([]byte, error)

ReadWithAnalytics is a wrapper to plugin.Read. Use it when you need to report a 'Read' invocation to analytics. Otherwise, use plugin.Read.

func SchemaGraph

func SchemaGraph(e Entry) (*linkedhashmap.Map, error)

SchemaGraph returns e's schema graph. This is effectively a map[string]plugin.EntrySchema object that preserves insertion order (where the string is each entry's type ID).

func SetTestCache

func SetTestCache(c datastore.Cache) context.Context

SetTestCache sets the cache to the provided mock. It can only be called by the tests. Returns a context that includes a parent ID so later cache operations will succeed.

func Signal

func Signal(ctx context.Context, s Signalable, signal string) error

Signal signals the entry with the specified signal

func SignalWithAnalytics

func SignalWithAnalytics(ctx context.Context, s Signalable, signal string) error

SignalWithAnalytics is a wrapper to plugin.Signal. Use it when you need to report a 'Signal' invocation to analytics. Otherwise, use plugin.Signal.

func Size

func Size(ctx context.Context, e Entry) (uint64, error)

Size returns the size of readable data for an entry. It may call Read to do so.

func Stream

func Stream(ctx context.Context, s Streamable) (io.ReadCloser, error)

Stream streams the entry's content for updates.

func StreamWithAnalytics

func StreamWithAnalytics(ctx context.Context, s Streamable) (io.ReadCloser, error)

StreamWithAnalytics is a wrapper to s#Stream. Use it when you need to report a 'Stream' invocation to analytics. Otherwise, use s#Stream.

func SupportedActionsOf

func SupportedActionsOf(entry Entry) []string

SupportedActionsOf returns all of the given entry's supported actions.

func TrackTime

func TrackTime(start time.Time, name string)

TrackTime helper is useful for timing functions. Use with `defer plugin.TrackTime(time.Now(), "funcname")`.

func TypeID

func TypeID(e Entry) string

TypeID returns the entry's type ID. It is needed by the API, so plugin authors should ignore this.

func UnsetTestCache

func UnsetTestCache()

UnsetTestCache unsets the test cache. It can only be called by the tests

func Write

func Write(ctx context.Context, a Writable, b []byte) error

Write sends the supplied buffer to the entry.

func WriteWithAnalytics

func WriteWithAnalytics(ctx context.Context, w Writable, b []byte) error

WriteWithAnalytics is a wrapper to w#Write. Use it when you need to report an 'Write' invocation to analytics. Otherwise, use w#Write.

Types

type Action

type Action struct {
	Name     string `json:"name"`
	Protocol string `json:"protocol"`
	// contains filtered or unexported fields
}

Action represents a Wash action.

func DeleteAction

func DeleteAction() Action

DeleteAction represents the delete action

func ExecAction

func ExecAction() Action

ExecAction represents the exec action

func ListAction

func ListAction() Action

ListAction represents the list action

func ReadAction

func ReadAction() Action

ReadAction represents the read action

func SignalAction

func SignalAction() Action

SignalAction represents the signal action

func StreamAction

func StreamAction() Action

StreamAction represents the stream action

func WriteAction

func WriteAction() Action

WriteAction represents the append action

func (Action) IsSupportedOn

func (a Action) IsSupportedOn(entry Entry) bool

IsSupportedOn returns true if the action's supported on the specified entry, false otherwise.

type BlockReadable

type BlockReadable interface {
	Entry
	Read(ctx context.Context, size int64, offset int64) ([]byte, error)
}

BlockReadable is an entry with data that can be read in blocks. A BlockReadable entry must set its Size attribute. If you don't set it, the file size will be reported as 0 and reads will return an empty file.

type CleanupReader

type CleanupReader struct {
	io.ReadCloser
	Cleanup func()
}

CleanupReader is a wrapper for an io.ReadCloser that performs cleanup when closed.

func (CleanupReader) Close

func (c CleanupReader) Close() error

Close closes the reader it wraps, then calls the Cleanup function and returns any errors.

type Deletable

type Deletable interface {
	Entry
	Delete(context.Context) (bool, error)
}

Deletable is an entry that can be deleted. Entries that implement Delete should ensure that it and all its children are removed. If the entry has any dependencies that need to be deleted, then Delete should return an error.

If Delete returns true, then that means the entry was deleted. If Delete returns false, then that means the entry is marked for deletion by the plugin's API. You should return false if you anticipate delete taking a long time (> 30 seconds).

type DuplicateCNameErr

type DuplicateCNameErr struct {
	ParentID                 string
	FirstChildName           string
	FirstChildSlashReplacer  rune
	SecondChildName          string
	SecondChildSlashReplacer rune
	CName                    string
}

DuplicateCNameErr represents a duplicate cname error, which occurs when at least two children have the same cname.

func (DuplicateCNameErr) Error

func (c DuplicateCNameErr) Error() string

type Entry

type Entry interface {
	Metadata(ctx context.Context) (JSONObject, error)
	Schema() *EntrySchema
	// contains filtered or unexported methods
}

Entry is the interface for things that are representable by Wash's filesystem. This includes plugin roots; resources like containers and volumes; placeholders (e.g. the containers directory in the Docker plugin); read-only files like the metadata.json files for containers and EC2 instances; and more. It is a sealed interface, meaning you must use plugin.NewEntry when creating your plugin objects.

Metadata returns a complete description of the entry. See the EntryBase documentation for more details on when to override it.

Schema returns the entry's schema. See plugin.EntrySchema for more details.

func FindEntry

func FindEntry(ctx context.Context, start Entry, segments []string) (Entry, error)

FindEntry returns the child of start found by following the segments, or an error if it cannot be found.

type EntryAttributes

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

EntryAttributes represents an entry's attributes. We use a struct instead of a map for efficient memory allocation/deallocation, which is needed to make Parent#List fast.

Each of the setters supports the builder pattern, which enables you to do something like

attr := plugin.EntryAttributes{}
attr.
	SetCrtime(crtime).
	SetMtime(mtime)
entry.SetAttributes(attr)

func Attributes

func Attributes(e Entry) EntryAttributes

Attributes returns the entry's attributes.

func (*EntryAttributes) Atime

func (a *EntryAttributes) Atime() time.Time

Atime returns the entry's last access time

func (*EntryAttributes) Crtime

func (a *EntryAttributes) Crtime() time.Time

Crtime returns the entry's creation time

func (*EntryAttributes) Ctime

func (a *EntryAttributes) Ctime() time.Time

Ctime returns the entry's change time

func (*EntryAttributes) HasAtime

func (a *EntryAttributes) HasAtime() bool

HasAtime returns true if the entry has a last access time

func (*EntryAttributes) HasCrtime

func (a *EntryAttributes) HasCrtime() bool

HasCrtime returns true if the entry has a creation time

func (*EntryAttributes) HasCtime

func (a *EntryAttributes) HasCtime() bool

HasCtime returns true if the entry has a change time

func (*EntryAttributes) HasMode

func (a *EntryAttributes) HasMode() bool

HasMode returns true if the entry has a mode

func (*EntryAttributes) HasMtime

func (a *EntryAttributes) HasMtime() bool

HasMtime returns true if the entry has a last modified time

func (*EntryAttributes) HasOS

func (a *EntryAttributes) HasOS() bool

HasOS returns true if the entry has information about its OS

func (*EntryAttributes) HasSize

func (a *EntryAttributes) HasSize() bool

HasSize returns true if the entry has a size

func (EntryAttributes) MarshalJSON

func (a EntryAttributes) MarshalJSON() ([]byte, error)

MarshalJSON marshals the entry's attributes to JSON. It takes a value receiver so that the attributes are still marshaled when they're referenced as interface{} objects. See https://stackoverflow.com/a/21394657 for more details.

func (*EntryAttributes) Mode

func (a *EntryAttributes) Mode() os.FileMode

Mode returns the entry's mode

func (*EntryAttributes) Mtime

func (a *EntryAttributes) Mtime() time.Time

Mtime returns the entry's last modified time

func (*EntryAttributes) OS

func (a *EntryAttributes) OS() OS

OS returns the entry's operating system information

func (*EntryAttributes) SetAtime

func (a *EntryAttributes) SetAtime(atime time.Time) *EntryAttributes

SetAtime sets the entry's last access time

func (*EntryAttributes) SetCrtime

func (a *EntryAttributes) SetCrtime(crtime time.Time) *EntryAttributes

SetCrtime sets the entry's creation time

func (*EntryAttributes) SetCtime

func (a *EntryAttributes) SetCtime(ctime time.Time) *EntryAttributes

SetCtime sets the entry's change time

func (*EntryAttributes) SetMode

func (a *EntryAttributes) SetMode(mode os.FileMode) *EntryAttributes

SetMode sets the entry's mode

func (*EntryAttributes) SetMtime

func (a *EntryAttributes) SetMtime(mtime time.Time) *EntryAttributes

SetMtime sets the entry's last modified time

func (*EntryAttributes) SetOS

func (a *EntryAttributes) SetOS(os OS) *EntryAttributes

SetOS sets the entry's operating system information

func (*EntryAttributes) SetSize

func (a *EntryAttributes) SetSize(size uint64) *EntryAttributes

SetSize sets the entry's size

func (*EntryAttributes) Size

func (a *EntryAttributes) Size() uint64

Size returns the entry's Size

func (*EntryAttributes) ToMap

func (a *EntryAttributes) ToMap() map[string]interface{}

ToMap converts the entry's attributes to a map, which makes it easier to write generic code on them.

func (*EntryAttributes) UnmarshalJSON

func (a *EntryAttributes) UnmarshalJSON(data []byte) error

UnmarshalJSON unmarshals the entry's attributes from JSON.

type EntryBase

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

EntryBase implements Entry, making it easy to create new entries. You should use plugin.NewEntry to create new EntryBase objects.

Each of the setters supports the builder pattern, which enables you to do something like

e := plugin.NewEntry("foo")
e.
	DisableCachingFor(plugin.ListOp).
	Attributes().
	SetCrtime(crtime).
	SetMtime(mtime).
	SetMeta(meta)

func NewEntry

func NewEntry(name string) EntryBase

NewEntry creates a new entry

func (*EntryBase) Attributes

func (e *EntryBase) Attributes() *EntryAttributes

Attributes returns a pointer to the entry's attributes. Use it to individually set the entry's attributes

func (*EntryBase) DisableCachingFor

func (e *EntryBase) DisableCachingFor(op defaultOpCode) *EntryBase

DisableCachingFor disables caching for the specified op

func (*EntryBase) DisableDefaultCaching

func (e *EntryBase) DisableDefaultCaching() *EntryBase

DisableDefaultCaching disables the default caching for List, Open and Metadata.

func (*EntryBase) ID

func (e *EntryBase) ID() string

ID returns the entry's ID. It won't panic on an empty string. See ID() for more detail. This exists primarily to support the `external` package.

func (*EntryBase) IsInaccessible

func (e *EntryBase) IsInaccessible() bool

IsInaccessible returns whether the entry is inaccessible.

func (*EntryBase) MarkInaccessible

func (e *EntryBase) MarkInaccessible(ctx context.Context, err error)

MarkInaccessible sets the inaccessible attribute and logs a message about why the entry is inaccessible.

func (*EntryBase) Metadata

func (e *EntryBase) Metadata(ctx context.Context) (JSONObject, error)

Metadata returns the entry's partial metadata. Override this if e has additional metadata properties that couldn't be included in the partial metadata because doing so would have slowed down parent#List.

func (*EntryBase) Name

func (e *EntryBase) Name() string

Name returns the entry's name as it was passed into plugin.NewEntry. You should use e.Name() when making the appropriate API calls within your plugin.

func (*EntryBase) Prefetched

func (e *EntryBase) Prefetched() *EntryBase

Prefetched marks the entry as a prefetched entry. A prefetched entry is an entry that was fetched as part of a batch operation that fetched multiple levels of hierarchy at once. Volume directories and files are good examples of prefetched entries (see the volume package for more details).

func (*EntryBase) SetAttributes

func (e *EntryBase) SetAttributes(attr EntryAttributes) *EntryBase

SetAttributes sets the entry's attributes. Use it to set the entry's attributes in a single operation, which is useful when you've already pre-computed them.

func (*EntryBase) SetPartialMetadata

func (e *EntryBase) SetPartialMetadata(obj interface{}) *EntryBase

SetPartialMetadata sets the entry's partial metadata. This is typically the raw object that's returned by the plugin API's List endpoint, or a wrapper that includes the raw object + some additional information. For example, if the entry represents a Docker container, then obj would be a Container struct. If the entry represents a Docker volume, then obj would be a Volume struct.

In general, the partial metadata is the subset of metadata that can be fetched "quickly" s.t. parent#List isn't slowed down.

SetPartialMetadata will panic if obj does not serialize to a JSON object.

func (*EntryBase) SetSlashReplacer

func (e *EntryBase) SetSlashReplacer(char rune) *EntryBase

SetSlashReplacer overrides the default '/' replacer '#' to char. The '/' replacer is used when determining the entry's cname. See plugin.CName for more details.

func (*EntryBase) SetTTLOf

func (e *EntryBase) SetTTLOf(op defaultOpCode, ttl time.Duration) *EntryBase

SetTTLOf sets the specified op's TTL

func (*EntryBase) SetTestID

func (e *EntryBase) SetTestID(id string)

SetTestID sets the entry's cache ID for testing. It can only be called by the tests.

func (*EntryBase) String

func (e *EntryBase) String() string

String returns a unique identifier for the entry suitable for logging and error messages.

func (*EntryBase) TTLOf

func (e *EntryBase) TTLOf(op defaultOpCode) time.Duration

TTLOf returns the TTL set for the specified op

type EntryMap

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

EntryMap is a thread-safe map of <entry_cname> => <entry_object>. It's API is (mostly) symmetric with sync.Map.

func List

func List(ctx context.Context, p Parent) (*EntryMap, error)

List lists the parent's children. It returns an EntryMap to optimize querying a specific entry.

Note that List's results could be cached.

func ListWithAnalytics

func ListWithAnalytics(ctx context.Context, p Parent) (*EntryMap, error)

ListWithAnalytics is a wrapper to plugin.List. Use it when you need to report a 'List' invocation to analytics. Otherwise, use plugin.List

func (*EntryMap) Delete

func (m *EntryMap) Delete(cname string)

Delete deletes the entry from the map

func (*EntryMap) Len

func (m *EntryMap) Len() int

Len returns the number of entries in the map

func (*EntryMap) Load

func (m *EntryMap) Load(cname string) (Entry, bool)

Load retrieves an entry

func (*EntryMap) Map

func (m *EntryMap) Map() map[string]Entry

Map returns m's underlying map. It can only be called by the tests.

func (*EntryMap) Range

func (m *EntryMap) Range(f func(string, Entry) bool)

Range iterates over the map, applying f to each (cname, entry) pair. If f returns false, then Each will break out of the loop.

type EntrySchema

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

EntrySchema represents an entry's schema. Use plugin.NewEntrySchema to create instances of these objects.

func NewEntrySchema

func NewEntrySchema(e Entry, label string) *EntrySchema

NewEntrySchema returns a new EntrySchema object with the specified label.

func Schema

func Schema(e Entry) (*EntrySchema, error)

Schema returns the entry's schema.

func (*EntrySchema) AddSignal

func (s *EntrySchema) AddSignal(name string, description string) *EntrySchema

AddSignal adds the given signal to s' supported signals. See https://puppetlabs.github.io/wash/docs#signal for a list of common signal names. You should try to re-use these names if you can.

func (*EntrySchema) AddSignalGroup

func (s *EntrySchema) AddSignalGroup(name string, regex string, description string) *EntrySchema

AddSignalGroup adds the given signal group to s' supported signals

func (*EntrySchema) IsSingleton

func (s *EntrySchema) IsSingleton() *EntrySchema

IsSingleton marks the entry as a singleton entry.

func (EntrySchema) MarshalJSON

func (s EntrySchema) MarshalJSON() ([]byte, error)

MarshalJSON marshals the entry's schema to JSON. It takes a value receiver so that the entry schema's still marshalled when it's referenced as an interface{} object. See https://stackoverflow.com/a/21394657 for more details.

Note that UnmarshalJSON is not implemented since that is not how plugin.EntrySchema objects are meant to be used.

func (*EntrySchema) SetDescription

func (s *EntrySchema) SetDescription(description string) *EntrySchema

SetDescription sets the entry's description.

func (*EntrySchema) SetMetadataSchema

func (s *EntrySchema) SetMetadataSchema(obj interface{}) *EntrySchema

SetMetadataSchema sets Entry#Metadata's schema. obj is an empty struct that will be marshalled into a JSON schema. SetMetadataSchema will panic if obj is not a struct.

NOTE: Only use SetMetadataSchema if you're overriding Entry#Metadata. Otherwise, use SetPartialMetadataSchema.

func (*EntrySchema) SetPartialMetadataSchema

func (s *EntrySchema) SetPartialMetadataSchema(obj interface{}) *EntrySchema

SetPartialMetadataSchema sets the partial metadata's schema. obj is an empty struct that will be marshalled into a JSON schema. SetPartialMetadataSchema will panic if obj is not a struct.

type ExecCommand

type ExecCommand interface {
	OutputCh() <-chan ExecOutputChunk
	ExitCode() (int, error)
}

ExecCommand represents a command that was invoked by a call to Exec. It is a sealed interface, meaning you must use plugin.NewExecCommand to create instances of these objects.

OutputCh returns a channel containing timestamped chunks of the command's stdout/stderr.

ExitCode returns the command's exit code. It will block until the command's exit code is set, or until the execution context is cancelled. ExitCode will return an error if it fails to fetch the command's exit code.

func Exec

func Exec(ctx context.Context, e Execable, cmd string, args []string, opts ExecOptions) (ExecCommand, error)

Exec execs the command on the given entry.

func ExecWithAnalytics

func ExecWithAnalytics(ctx context.Context, e Execable, cmd string, args []string, opts ExecOptions) (ExecCommand, error)

ExecWithAnalytics is a wrapper to e#Exec. Use it when you need to report an 'Exec' invocation to analytics. Otherwise, use e#Exec.

type ExecCommandImpl

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

ExecCommandImpl implements the plugin.ExecCommand interface. Use plugin.NewExecCommand to create instances of these objects.

ExecCommandImpl provides Stdout/Stderr streams that you can wire-up to your plugin's API. These streams ensure that your API's stdout/stderr ordering is preserved. For example, if your API sends over Stderr, Stdout, and Stderr packets (in that order), then ExecCommand's OutputCh will stream them as Stderr, Stdout, and Stderr packets to your clients.

Once the command's finished its execution, use SetExitCode to set the command's exit code. If your API fails to retrieve the command's exit code, then use SetExitCodeErr to set an appropriate error that ExitCode() can return.

ExecCommandImpl also includes helpers that handle context-cancellation related cleanup for you. plugin.NewExecCommand ensures that the OutputCh is closed upon context-cancellation so that clients streaming your command's output are not blocked. SetStopFunc ensures that the exec'ing command is stopped upon context-cancellation, which prevents orphaned processes.

See Container#Exec in the Docker plugin and ExecSSH in the transport package for examples of how ExecCommandImpl is used.

func NewExecCommand

func NewExecCommand(ctx context.Context) *ExecCommandImpl

NewExecCommand creates a new ExecCommandImpl object whose lifetime is tied to the passed-in execution context. This ctx should match what's passed into Execable#Exec. Note that NewExecCommand ensures that the OutputCh is closed when ctx is cancelled.

func (*ExecCommandImpl) CloseStreamsWithError

func (cmd *ExecCommandImpl) CloseStreamsWithError(err error)

CloseStreamsWithError closes the command's stdout/stderr streams with the given error.

func (*ExecCommandImpl) ExitCode

func (cmd *ExecCommandImpl) ExitCode() (int, error)

ExitCode implements ExecCommand#ExitCode

func (*ExecCommandImpl) OutputCh

func (cmd *ExecCommandImpl) OutputCh() <-chan ExecOutputChunk

OutputCh implements ExecCommand#OutputCh

func (*ExecCommandImpl) SetExitCode

func (cmd *ExecCommandImpl) SetExitCode(exitCode int)

SetExitCode sets the command's exit code that will be returned by cmd.ExitCode().

func (*ExecCommandImpl) SetExitCodeErr

func (cmd *ExecCommandImpl) SetExitCodeErr(err error)

SetExitCodeErr sets the error that will be returned by cmd.ExitCode(). Use it if your plugin API fails to get the command's exit code.

func (*ExecCommandImpl) SetStopFunc

func (cmd *ExecCommandImpl) SetStopFunc(stopFunc func())

SetStopFunc sets the function that stops the running command. stopFunc is called when cmd.ctx is cancelled.

NOTE: SetStopFunc can be used to avoid orphaned processes.

func (*ExecCommandImpl) Stderr

func (cmd *ExecCommandImpl) Stderr() *OutputStream

Stderr returns the command's stderr stream. Attach this to your plugin API's stderr stream.

func (*ExecCommandImpl) Stdout

func (cmd *ExecCommandImpl) Stdout() *OutputStream

Stdout returns the command's stdout stream. Attach this to your plugin API's stdout stream.

type ExecOptions

type ExecOptions struct {
	// Stdin can be used to pass a stream of input to write to stdin when executing the command.
	// It is not included in ExecOption's JSON serialization.
	Stdin io.Reader `json:"-"`

	// Tty instructs the executor to allocate a TTY (pseudo-terminal), which lets Wash communicate
	// with the running process via its Stdin. The TTY is used to send a process termination signal
	// (Ctrl+C) via Stdin when the passed-in Exec context is cancelled.
	//
	// NOTE TO PLUGIN AUTHORS: The Tty option is only relevant for executors that do not have an API
	// endpoint to stop a running command (e.g. Docker, Kubernetes). If your executor does have an
	// API endpoint to stop a running command, then ignore the Tty option. Note that the reason we
	// make Tty an option instead of having the relevant executors always attach a TTY is because
	// attaching a TTY can change the behavior of the command that's being executed.
	//
	// NOTE TO CALLERS: The Tty option is useful for executing your own stream-like commands (e.g.
	// tail -f), because it ensures that there are no orphaned processes after the request is
	// cancelled/finished.
	Tty bool `json:"tty"`

	// Elevate execution to run as a privileged user if not already running as a privileged user.
	Elevate bool `json:"elevate"`
}

ExecOptions is a struct we can add new features to that must be serializable to JSON. Examples of potential features: user, privileged, map of environment variables, timeout.

type ExecOutputChunk

type ExecOutputChunk struct {
	StreamID  ExecPacketType
	Timestamp time.Time
	Data      string
	Err       error
}

ExecOutputChunk is a struct containing a chunk of the Exec'ed cmd's output.

type ExecPacketType

type ExecPacketType = string

ExecPacketType identifies the packet type.

const (
	Stdout ExecPacketType = "stdout"
	Stderr ExecPacketType = "stderr"
)

Enumerates packet types.

type Execable

type Execable interface {
	Entry
	Exec(ctx context.Context, cmd string, args []string, opts ExecOptions) (ExecCommand, error)
}

Execable is an entry that can have a command run on it.

type HasWrappedTypes

type HasWrappedTypes interface {
	Root
	WrappedTypes() SchemaMap
}

HasWrappedTypes is an interface that's used by the EntrySchema#SetMeta*Schema methods to return the right metadata schema for wrapped types. Plugin roots should implement this interface if the plugin's SDK wraps primitive types like date, integer, number, string, boolean, etc. See kubernetes/root.go for an example of when WrappedTypes is used.

NOTE: Type aliases like "type Time = time.Time" do NOT count as wrapped types. Pointers also don't count. Only promoted types ("type Time time.Time") and wrapper structs ("struct Time { t time.Time }") count.

NOTE: Without WrappedTypes, the underlying JSON schema library will treat promoted types and wrapper structs as JSON objects, which would be incorrect. This, unfortunately, is a limitation of Go's reflect package.

type InvalidInputErr

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

InvalidInputErr indicates that the method invocation received invalid input (e.g. plugin.Signal received an unsupported signal).

func (InvalidInputErr) Error

func (e InvalidInputErr) Error() string

type JSONObject

type JSONObject = map[string]interface{}

JSONObject is a typedef to a map[string]interface{} object.

func Metadata

func Metadata(ctx context.Context, e Entry) (JSONObject, error)

Metadata returns the entry's metadata. Note that Metadata's results could be cached.

func PartialMetadata

func PartialMetadata(e Entry) JSONObject

PartialMetadata returns the entry's partial metadata, a subset of the entry's metadata that is typically provided by the plugin API's List endpoint. If the entry didn't specify any partial metadata, then this returns Attributes(e).ToMap() to enforce the "attributes are a subset of the partial metadata" invariant.

func ToJSONObject

func ToJSONObject(v interface{}) JSONObject

ToJSONObject serializes v to a JSON object. It will panic if the serialization fails.

type JSONSchema

type JSONSchema = jsonschema.Schema

JSONSchema represents a JSON schema

func BooleanSchema

func BooleanSchema() *JSONSchema

BooleanSchema represents a boolean's schema (bool)

func IntegerSchema

func IntegerSchema() *JSONSchema

IntegerSchema represents an integer's schema (int)

func NumberSchema

func NumberSchema() *JSONSchema

NumberSchema represents a number's schema (float64)

func StringSchema

func StringSchema() *JSONSchema

StringSchema represents a string's schema (string)

func TimeSchema

func TimeSchema() *JSONSchema

TimeSchema represents the schema of a time.Time object

type MetadataJSONFile

type MetadataJSONFile struct {
	EntryBase
	// contains filtered or unexported fields
}

MetadataJSONFile represents a metadata.json file that contains another entry's metadata.

func NewMetadataJSONFile

func NewMetadataJSONFile(ctx context.Context, other Entry) (*MetadataJSONFile, error)

NewMetadataJSONFile creates a new MetadataJSONFile. If caching Metadata on the `other` entry is disabled, it will use that to compute the file size upfront.

func (*MetadataJSONFile) Read

func (m *MetadataJSONFile) Read(ctx context.Context) ([]byte, error)

Read returns the metadata of the `other` entry as its content.

func (*MetadataJSONFile) Schema

func (m *MetadataJSONFile) Schema() *EntrySchema

Schema defines the schema of a metadata.json file.

type MethodSignature

type MethodSignature int

MethodSignature defines what method signature is supported for a method.

const (
	UnsupportedSignature MethodSignature = iota
	DefaultSignature
	BlockReadableSignature
)

Defines different method signatures.

type OS

type OS struct {
	// LoginShell describes the type of shell execution occurs in. It can be used
	// by the caller to decide what type of commands to run.
	LoginShell Shell
}

OS contains information about the operating system of a compute-like entry

func (OS) ToMap

func (o OS) ToMap() map[string]interface{}

ToMap converts the OS struct data to a map.

type OutputStream

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

OutputStream represents stdout/stderr.

func (*OutputStream) CloseWithError

func (s *OutputStream) CloseWithError(err error)

CloseWithError sends the given error before closing the OutputStream. It will noop if the OutputStream's already closed.

func (*OutputStream) Write

func (s *OutputStream) Write(data []byte) (int, error)

func (*OutputStream) WriteWithTimestamp

func (s *OutputStream) WriteWithTimestamp(timestamp time.Time, data []byte) error

WriteWithTimestamp writes the given data with the specified timestamp

type Parent

type Parent interface {
	Entry
	// TODO: "nil" schemas mean that the schema's unknown. This condition's necessary for
	// the plugin registry b/c external plugins may not have a schema. However, core plugins
	// should never return a "nil" schema -- their schema's always known. Since this specification
	// affects core plugin authors, it should be cleaned up once the metadata schema + external
	// plugin schema work is finished.
	ChildSchemas() []*EntrySchema
	List(context.Context) ([]Entry, error)
}

Parent is an entry with children. It will be represented as a directory in the Wash filesystem. All parents must implement ChildSchemas, which is useful for documenting your plugin's hierarchy via the stree command, and for optimizing `wash find`'s traversal by eliminating non-satisfying paths. Your implementation of ChildSchemas should be something like

return []*plugin.EntrySchema{
	(&childObj1{}).Schema(),
	(&childObj2{}).Schema(),
	...
	(&childObjN{}).Schema(),
}

For example,

return []*plugin.EntrySchema{
	(&containerLogFile{}).Schema(),
	(&containerMetadata{}).Schema(),
	(&vol.FS{}).Schema(),
}

is the implementation of ChildSchemas for a Docker container.

type Readable

type Readable interface {
	Entry
	Read(context.Context) ([]byte, error)
}

Readable is an entry with data that can be read.

type Registry

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

Registry represents the plugin registry. It is also Wash's root.

func NewRegistry

func NewRegistry() *Registry

NewRegistry creates a new plugin registry object

func (*Registry) ChildSchemas

func (r *Registry) ChildSchemas() []*EntrySchema

ChildSchemas only makes sense for core plugin roots

func (*Registry) List

func (r *Registry) List(ctx context.Context) ([]Entry, error)

List all of Wash's loaded plugins

func (*Registry) Plugins

func (r *Registry) Plugins() map[string]Root

Plugins returns a map of the currently registered plugins. It should not be called while registering plugins.

func (*Registry) RegisterPlugin

func (r *Registry) RegisterPlugin(root Root, config map[string]interface{}) error

RegisterPlugin initializes the given plugin and adds it to the registry if initialization was successful.

func (*Registry) Schema

func (r *Registry) Schema() *EntrySchema

Schema only makes sense for core plugin roots

type Root

type Root interface {
	Parent
	Init(map[string]interface{}) error
}

Root represents the plugin root. The Init function is passed a config map representing plugin-specific configuration.

type SchemaMap

type SchemaMap = map[interface{}]*JSONSchema

SchemaMap represents a map of <type> => <JSON schema>.

type Shell

type Shell int

Shell describes a command shell.

const (
	UnknownShell Shell = iota
	POSIXShell
	PowerShell
)

Defines specific Shell classes you can configure

func (Shell) String

func (sh Shell) String() string

type SignalSchema

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

SignalSchema represents a given signal/signal group's schema

func (*SignalSchema) Description

func (s *SignalSchema) Description() string

Description returns the signal/signal group's name

func (*SignalSchema) IsGroup

func (s *SignalSchema) IsGroup() bool

IsGroup returns true if s is a signal group's schema. This is true if s.Regex() != nil

func (SignalSchema) MarshalJSON

func (s SignalSchema) MarshalJSON() ([]byte, error)

MarshalJSON marshals the signal schema to JSON. It takes a value receiver so that the entry schema's still marshalled when it's referenced as an interface{} object. See https://stackoverflow.com/a/21394657 for more details.

func (*SignalSchema) Name

func (s *SignalSchema) Name() string

Name returns the signal/signal group's name

func (*SignalSchema) Regex

func (s *SignalSchema) Regex() *regexp.Regexp

Regex returns a regex describing an arbitrary signal in the signal group.

func (*SignalSchema) SetDescription

func (s *SignalSchema) SetDescription(description string) *SignalSchema

SetDescription sets the signal/signal group's description. This should only be called by the tests.

func (*SignalSchema) SetName

func (s *SignalSchema) SetName(name string) *SignalSchema

SetName sets the signal/signal group's name. This should only be called by the tests.

func (*SignalSchema) SetRegex

func (s *SignalSchema) SetRegex(regex *regexp.Regexp) *SignalSchema

SetRegex sets the signal group's regex. This should only be called by the tests.

func (*SignalSchema) UnmarshalJSON

func (s *SignalSchema) UnmarshalJSON(bytes []byte) error

UnmarshalJSON unmarshals the signal schema JSON.

type Signalable

type Signalable interface {
	Entry
	Signal(context.Context, string) error
}

Signalable is an entry that can be signaled. Signal should return nil if the signal was successfully sent. Otherwise, it should return an error explaining why the signal was not sent.

NOTE: You can assume that the sent signal is downcased and valid.

type Streamable

type Streamable interface {
	Entry
	Stream(context.Context) (io.ReadCloser, error)
}

Streamable is an entry that returns a stream of updates.

type Writable

type Writable interface {
	Entry
	Write(context.Context, []byte) error
}

Writable is an entry that we can write new data to. What that means can be implementation-specific; it could be overwriting a file, submitting a configuration change to an API, or writing data to a queue. It doesn't support a concept of a partial write.

Writable can be implemented with or without Readable/BlockReadable. If an entry is only Writable, then only full writes (starting from offset 0) are allowed, anything else initiated by the filesystem will result in an error.

Directories

Path Synopsis
Package aws presents a filesystem hierarchy for AWS resources.
Package aws presents a filesystem hierarchy for AWS resources.
Package docker presents a filesystem hierarchy for Docker resources.
Package docker presents a filesystem hierarchy for Docker resources.
Package gcp presents a filesystem hierarchy for Google Cloud Platform resources.
Package gcp presents a filesystem hierarchy for Google Cloud Platform resources.
Package kubernetes presents a filesystem hierarchy for Kubernetes resources.
Package kubernetes presents a filesystem hierarchy for Kubernetes resources.

Jump to

Keyboard shortcuts

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