Bootleg.DSL (bootleg v0.13.0) View Source
Configuration DSL for Bootleg.
Link to this section Summary
Functions
Defines an after hook for a task.
Defines a before hook for a task.
Fetches all key/value pairs currently defined in the Bootleg configuration.
Fetches the value for the supplied key from the Bootleg configuration. If the provided
key is a Tuple
, the first element is considered the key, the second value is considered
the default value (and returned without altering the config) in case the key has not
been set. This uses the same semantics as Keyword.get/3
.
Sets key
in the Bootleg configuration to value
.
Downloads files from remote hosts to the local machine.
Invokes the task identified by task
.
Executes commands on all remote hosts.
Executes commands on all remote hosts within a role.
Executes commands on a remote host.
Defines a role.
Defines a task idefintied by task
.
Uploads a local file to remote hosts.
Link to this section Functions
Defines an after hook for a task.
Behaves exactly like a before hook, but executes after the task has run. See before_task/2
for more details.
use Bootleg.DSL
after_task :build, :store_artifact
after_task :deploy do
Notify.team "Deployed!"
end
Defines a before hook for a task.
A hook is a piece of code that is executed before/after a task has been run. The hook can
either be a standalone code block, or the name of another task. Hooks are executed in an
unconditional fashion. Only an uncaught exeception will prevent futher execution. If a task
name is provided, it will be invoked via invoke/1
.
Just like with invoke/1
, a task does not need to be defined to have a hook registered for
it, nor does the task need to be defined in order to be triggered via a hook. Tasks may also
be defined at a later point, provided execution has not begun.
If multiple hooks are defined for the same task, they are executed in the order they were originally defined.
use Bootleg.DSL
before_task :build, :checksum_code
before_task :deploy do
Notify.team "Here we go!"
end
Relying on the ordering of hook execution is heavily discouraged. It's better to explicitly define the order using extra tasks and hooks. For example
use Bootleg.DSL
before_task :build, :do_first
before_task :build, :do_second
would be much better written as
use Bootleg.DSL
before_task :build, :do_first
before_task :do_first, :do_second
Fetches all key/value pairs currently defined in the Bootleg configuration.
Fetches the value for the supplied key from the Bootleg configuration. If the provided
key is a Tuple
, the first element is considered the key, the second value is considered
the default value (and returned without altering the config) in case the key has not
been set. This uses the same semantics as Keyword.get/3
.
use Bootleg.DSL
config :foo, :bar
# local_foo will be :bar
local_foo = config :foo
# local_foo will be :bar still, as :foo already has a value
local_foo = config {:foo, :car}
# local_hello will be :world, as :hello has not been defined yet
local_hello = config {:hello, :world}
config :hello, nil
# local_hello will be nil, as :hello has a value of nil now
local_hello = config {:hello, :world}
Sets key
in the Bootleg configuration to value
.
One of the cornerstones of the Bootleg DSL, config/2
is used to pass configuration options
to Bootleg. See the documentation for the specific task you are trying to configure for what
keys it supports.
use Bootleg.DSL
config :app, :my_cool_app
config :version, "1.0.0"
Downloads files from remote hosts to the local machine.
Downloading works much like remote/3
, but instead of transferring shell commands over SSH,
it transfers files via SCP. The remote host does need to support SCP, which should be provided
by most SSH implementations automatically.
role
can either be a single role name, a list of roles, or a list of roles and filter
attributes. The special :all
role is also supported. See remote/3
for details. Note that
if multiple hosts match, files will be downloaded from all matching hosts, and any duplicate
file names will result in collisions. The exact semantics of how that works are handled by
SSHKit.SCP
, but in general the file transfered last wins.
local_path
is a path to local directory or file where the downloaded files(s) should be placed.
Absolute paths will be respected, relative paths will be resolved relative to the current working
directory of the invoking shell. If the local_path
does not exist in the local file system, an
attempt will be made to create the missing directory. This does not handle nested directories,
and a File.Error
will be raised.
remote_path
is the file or directory to be copied from the remote hosts. If a directory is
specified, its contents will be recursively copied. Relative paths will be resolved relative to
the remote workspace, absolute paths will be respected.
The files on the local host are created using the current user's uid
/gid
and umask
.
use Bootleg.DSL
# copies ./my_file from the remote host to ./new_name locally
download :app, "my_file", "new_name"
# copies ./my_file from the remote host to the file ./a_dir/my_file locally
download :app, "my_file", "a_dir"
# recursively copies ./some_dir on the remote host to ./new_dir locally, ./new_dir
# will be created if missing
download :app, "some_dir", "new_dir"
# copies /foo/my_file on the remote host to /tmp/foo locally
download :app, "/foo/my_file", "/tmp/foo"
Specs
invoke(atom()) :: :ok
Invokes the task identified by task
.
This is one of the cornerstones of the Bootleg DSL. Executing a task first calls any registered
before_task/2
hooks, then executes the task itself (which was defined via task/2
), then any
registered after_task/2
hooks.
The execution of the hooks and the task are unconditional. Return values are ignored, though an
uncuaght exception will stop further execution. The task
does not need to exist. Any
hooks for a task with the name of task
will still be executed, and no error or warning will be
emitted. This can be used to create events which a developer wants to be able to install hooks
around without needing to define no-op tasks.
invoke/1
executes immediately, so it should always be called from inside a task. If it's placed
directly inside config/deploy.exs
, the task will be invoked when the configuration is first
read. This is probably not what is desired.
use Bootleg.DSL
task :hello do
IO.puts "Hello?"
invoke :world
end
task :world do
IO.puts "World!"
end
Executes commands on all remote hosts.
This is equivalent to calling remote/2
with a role of :all
.
Executes commands on all remote hosts within a role.
This is equivalent to calling remote/3
with an options
of []
.
Executes commands on a remote host.
This is the workhorse of the DSL. It executes shell commands on all hosts associated with
the role
. If any of the shell commands exits with a non-zero status, execution will be stopped
and an SSHError
will be raised.
lines
can be a List
of commands to execute, or a code block where each line's return value is
used as a command. Each command will be simulataneously executed on all hosts in the role. Once
all hosts have finished executing the command, the next command in the list will be sent.
options
is an optional Keyword
list of options to customize the remote invocation. Currently two
keys are supported:
filter
takes aKeyword
list of host options to filter with. Any host whose options match the filter will be included in the remote execution. A host matches if it has all of the filtering options defined and the values match (via==/2
) the filter.cd
changes the working directory of the remote shell prior to executing the remote commands. The options takes either an absolute or relative path, with relative paths being defined relative to the workspace configured for the role, or the default working directory of the shell if no workspace is defined.
role
can be a single role, a list of roles, or the special role :all
(all roles). If the same host
exists in multiple roles, the commands will be run once for each role where the host shows up. In the
case of multiple roles, each role is processed sequentially.
Returns the results to the caller, per command and per host. See Bootleg.SSH.run!
for more details.
use Bootleg.DSL
remote :build, ["uname -a", "date"]
remote :build do
"ls -la"
"echo " <> Time.to_string(Time.utc_now) <> " > local_now"
end
# will raise an error since `false` exits with a non-zero status
remote :build, ["false", "touch never_gonna_happen"]
# runs for hosts found in all roles
remote do: "hostname"
remote :all, do: "hostname"
# runs for hosts found in :build first, then for hosts in :app
remote [:build, :app], do: "hostname"
role :build, "host2.example.com"
role :build, "host1.example.com", primary: true, another_attr: :cat
# only runs on `host1.example.com`
remote :build, filter: [primary: true] do
"hostname"
end
# runs on `host1.example.com` inside the `tmp` directory found in the workspace
remote :build, filter: [primary: true], cd: "tmp/" do
"hostname"
end
Defines a role.
Roles are a collection of hosts and their options that are responsible for the same function, for example building a release, archiving a release, or executing commands against a running application.
name
is the name of the role, and is globally unique. Calling role/3
multiple times with
the same name will result in the host lists being merged. If the same host shows up mutliple
times, it will have its options
merged. The name :all
is reserved and cannot be used here.
hosts
can be a single hostname, or a List
of hostnames.
options
is an optional Keyword
used to provide configuration details about a specific host
(or collection of hosts). Certain options are passed to SSH directly (see
Bootleg.SSH.ssh_options/0
), others are used internally (user
for example, is used
by both SSH and Git), and unknown options are simply stored. In the future remote/1,2
will
allow for host filtering based on role options. Some Bootleg extensions may also add support
for additional options.
use Bootleg.DSL
role :build, ["build1.example.com", "build2.example.com"], user: "foo", identity: "~/.ssh/id_rsa"
Defines a task idefintied by task
.
This is one of the cornerstones of the Bootleg DSL. It takes a task name (task
) a block of code
and registers the code to be executed when task
is invoked. Inside the block, the full Bootleg
DSL is available.
A warning will be emitted if a task is redefined, unless the override
option is specified with a value of true
.
use Bootleg.DSL
task :hello do
IO.puts "Hello World!"
end
Tasks can override existing tasks:
use Bootleg.DSL
task :update, override: true do
alias Bootleg.UI
UI.info("No longer using stock update task")
end
Uploads a local file to remote hosts.
Uploading works much like remote/3
, but instead of transferring shell commands over SSH,
it transfers files via SCP. The remote host does need to support SCP, which should be provided
by most SSH implementations automatically.
role
can either be a single role name, a list of roles, or a list of roles and filter
attributes. The special :all
role is also supported. See remote/3
for details.
local_path
can either be a file or directory found on the local machine. If its a directory,
the entire directory will be recursively copied to the remote hosts. Relative paths are resolved
relative to the root of the local project.
remote_path
is the file or directory where the transfered files should be placed. The semantics
of how remote_path
is treated vary depending on what local_path
refers to. If local_path
points
to a file, remote_path
is treated as a file unless it's .
or ends in /
, in which case it's
treated as a directory and the filename of the local file will be used. If local_path
is a directory,
remote_path
is treated as a directory as well. Relative paths are resolved relative to the projects
remote workspace
. Missing directories are not implicilty created.
The files on the remote server are created using the authenticating user's uid
/gid
and umask
.
use Bootleg.DSL
# copies ./my_file to ./new_name on the remote host
upload :app, "my_file", "new_name"
# copies ./my_file to ./a_dir/my_file on the remote host. ./a_dir must already exist
upload :app, "my_file", "a_dir/"
# recursively copies ./some_dir to ./new_dir on the remote host. ./new_dir will be created if missing
upload :app, "some_dir", "new_dir"
# copies ./my_file to /tmp/foo on the remote host
upload :app, "my_file", "/tmp/foo"