wash is a Ruby gem that's meant to facilitate external plugin development for the Wash project. It does not have any external dependencies.
Plugin scripts that use this gem should adopt the following template:
require 'wash' # All other requires go here # These are all optional. However, they should be declared # before the subsequent Wash.run call #Wash.pretty_print #Wash.enable_entry_schemas #Wash.prefetch_entry_schemas Wash.run(<root_klass>, ARGV)
<root_klass> is the plugin root's class object. The plugin root must implement the
list methods. For example, if the plugin root is something like
class MyPluginRoot < :: def init(config) // ... end def list // ... end end
then the corresponding call to
Wash.run would be
All entries should have their own Ruby class corresponding to a specific kind of entry; this class must extend the
Wash::Entry base class. For example, a
VirtualMachine class should represent entries that are virtual machines; a
Database class represents entries that are databases; a
DockerContainer class represents Docker containers; a
GoodReadsBook represents a GoodReads book, etc. Each class should extend the
Wash::Entry base class.
The entry's supported Wash methods corresponds to instance methods on the entry's class. For example, something like
class VirtualMachine < :: def exec(cmd, args, opts) # ... end def stream # ... end end
exec. The calling conventions and return parameters for each method is described below:
init(config)should not return a value.
Hashcontaining the plugin config. Only invoked on the plugin root.
listshould return an array of
readshould return a
Stringcontaining the entry's content. For block-readable entries,
read(size, offset)should return a
sizebits of the entry's content starting at the given offset.
metadatashould return a
Hashcontaining the entry's full metadata.
streamshould never return during normal operation.
streamimplementations should use the
Wash::Streamerclass when writing their chunks.
exec(cmd, args, opts)should return
cmd's exit code.
execimplementations should write their stdout/stderr chunks to stdout/stderr. Note that
STDIN, if provided, can be accessed via the
opts[:stdin]key. When this function is called, Wash sets
$stdoutto ensure output is immediately available.
trueif the entry was deleted,
falseif the entry's deletion is in progress.
nilif the signal was successfully sent.
nilif the data's successfully written. Note that
data == STDIN.
Wash::Entry objects must set
@name (to a
String) when they're initialized. They may also set
@partial_metadata (to a
Hash) if they have metadata that's available at initialization.
Wash provides two types of core features - core entries and exec implementations - that plugins can use.
Core entries can be used when listing children. See the external plugin list docs for more on core entries. This gem provides helpers for using the
volume::fs core entry:
class Parent < Wash::Entry # When 'Wash.enable_entry_schemas' is used the VOLUMEFS entry needs to be included parent_of VOLUMEFS, ... def list [volumefs("fs", maxdepth: 2), ...] end end
Exec implementations provide an implementation of the
exec method so you don't need to define your own. For example if your entry works with SSH, then you can use Wash's SSH transport to implement its exec method. See the external plugin exec docs for more on exec implementations, including all the options available for the SSH transport. Request this transport with:
class Execable < :: def initialize(name) transport :ssh, host: name, user: 'root' end # When 'Wash.enable_entry_schemas' is used the 'exec' method still needs to be defined so it appears in the schema def exec raise 'implemented by transport' end end
Entry schemas are optional. They can be enabled via the
Wash.enable_entry_schemas configuration option.
wash gem provides convenient helpers for specifying Entry schemas. Below is an example showcasing some of the helpers
class Parent < :: label 'parent' is_singleton parent_of 'ChildOne', 'ChildTwo' def list # Should return instances of ChildOne/ChildTwo end end class ChildOne < :: label 'child_one' end class ChildTwo < :: label 'child_two' end