mirror of
https://github.com/capistrano/capistrano
synced 2023-03-27 23:21:18 -04:00
210 lines
8.3 KiB
Markdown
210 lines
8.3 KiB
Markdown
---
|
|
title: Properties
|
|
layout: default
|
|
---
|
|
|
|
Server objects in Capistrano essentially consist of a name and a hash: The name is the DNS
|
|
name (or IP address) and the hash contains the 'Properties' of the server. These
|
|
properties are of two sorts: ones required by Capistrano (_Capistrano Properties_) and
|
|
ones available for use by the Application (_Custom Properties_). These share the same
|
|
namespace (there is only one underlying hash!) so the names of custom properties are
|
|
restricted.
|
|
|
|
### Capistrano Properties
|
|
|
|
The Capistrano properties are those used to SSH into the server and those that support the
|
|
basic _role_ functionality. These are:
|
|
|
|
* `:user` - the name of the SSH user for the server
|
|
* `:password` - for the SSH user
|
|
* `:port` - the port number of the SSH daemon on the server
|
|
* `:roles` - an array of rolenames
|
|
* `:ssh_options` - a hash of SSH parameters (see below)
|
|
* `:primary` - a boolean that indicates whether the server should be considered primary or
|
|
not.
|
|
|
|
The `:user`, `:port` and `:password` may be specified as follows:
|
|
|
|
* As part of the hostname in the form 'user@host:port' without a password,
|
|
* In the properties `:user`, `:password` and `:port`, and
|
|
* In the property `:ssh_options` (with the same keys)
|
|
|
|
#### Precedence
|
|
|
|
The SSH related properties are set with the following precedence, beginning with the
|
|
highest:
|
|
|
|
* Property declarations on the server or role. The last property declaration overrides all
|
|
the previous server or role declarations
|
|
* Values specified in the hostname string
|
|
* Values in the server or role `:ssh_options` property
|
|
* The stage global variable `:ssh_options`
|
|
* The SSHKit backend `ssh_options`
|
|
* The settings in your local `~/.ssh/config` file
|
|
|
|
Note however that defaults taken from these places will _not_ be reflected back into the
|
|
server properties, so `host.user` will be nil if a lower precedence default is being used.
|
|
|
|
### Custom Properties
|
|
|
|
When using Capistrano as a general purpose deployment framework (above and beyond it's
|
|
traditional use for Rails deployments) it becomes important to be able to store additional
|
|
parameters. You can think of Capistrano as an _MVC_ framework for deployments, where the
|
|
stage file (representing all the relationships between application components) is the
|
|
_Model_, the tasks (enabling model changes to be actioned) are the _Controllers_, and the
|
|
actual physical embodiments (typically configuration files on running servers) are the
|
|
_Views_.
|
|
|
|
### Property Access from within Tasks
|
|
|
|
The properties on Capistrano server are accessible programmatically from a Capistrano
|
|
task. _Capistrano_ properties are available through methods on the host object itself and
|
|
_Custom_ properties via methods on the `properties` attribute of the host.
|
|
|
|
These methods have the expected names: `user`, `port` and so on. An exception is the
|
|
`ssh_config` which is available via the `netssh_options` method.
|
|
|
|
The following feature is new in Capistrano 3.3.6 and above.
|
|
|
|
Within the scope of an `on()` block, the host that is yielded is a *copy* of the underlying
|
|
host, which allows you to temporarily override any of the properties by calling the setter
|
|
method. An example is:
|
|
|
|
```ruby
|
|
on roles(:all) do |host|
|
|
host.user = 'root'
|
|
host.password = 'supersecret'
|
|
execute :yum, 'makecache'
|
|
end
|
|
```
|
|
|
|
This temporarily sets the SSH user to 'root' (with an appropriate password) without
|
|
affecting the SSH user defined for the server in the configuration.
|
|
|
|
### Property setting in Complex Configurations
|
|
|
|
As configurations involve more servers it helps to be able to define a set of
|
|
properties at the role level, and have those be overridden by a later definition at the
|
|
server level. This keeps your configuration as DRY as possible. A typical requirement is
|
|
defining a set of Redis servers which all have the same port parameter and are all slaves
|
|
except for one which is the master.
|
|
|
|
To allow this properties can be set at both the _Server_ and _Role_ level. The guiding
|
|
principle is that the properties are _merged_ and that __the last definition wins__.
|
|
In practice we finesse this slightly depending on the type of the properties value:
|
|
|
|
* _scalar_ values will be overridden
|
|
* _hash_ values will have their keys merged with duplicate keys taking on
|
|
the value of the last one.
|
|
* _array_ values will have subsequent entries appended to the array
|
|
|
|
#### Example of Server and Role Properties
|
|
|
|
The above Redis requirement can be met using the following declarations in the stage file:
|
|
|
|
```ruby
|
|
role :redis, %w{ r1.example.com r2.example.com r3.example.com }, redis: { port: 6379, master: false },
|
|
server 'r1.example.com', redis: { port: 6380, master: true }
|
|
```
|
|
|
|
#### Conventions for Role Properties
|
|
|
|
This is complicated by the fact that a single machine may serve multiple roles, and in
|
|
fact a single machine may need to do the same role twice! An example of this might be in a
|
|
development situation where you want a single machine to be the database server, a primary
|
|
Redis server and a slave Redis server.
|
|
|
|
To solve this problem we adopt a convention for the use of server properties:
|
|
|
|
* Server properties for a given role should be stored with the keyname equal to the role.
|
|
The contents of the property can be a scalar, array or hash.
|
|
|
|
* Multiple occurrences of a role on the same server should have the contents be an array,
|
|
in which the successive elements denote each instance.
|
|
|
|
The following example shows a configuration with multiple Redis and Sentinel roles on the
|
|
same server:
|
|
|
|
```ruby
|
|
server 'dev.local', roles: %w{db web redis sentinel worker}, primary: true,
|
|
redis: [ { name: 'resque', port: 6379, db: 0, downtime: 10, master: true },
|
|
{ name: 'resque', port: 6380, db: 0, downtime: 10 } ],
|
|
sentinel: [ { port: 26379 }, { port: 26380 }, { port: 26381 } ]
|
|
```
|
|
|
|
These properties can be accessed in the ordinary way, but to assist in obtaining them you
|
|
can use the `role_properties()` function (see below).
|
|
|
|
## Setting Properties
|
|
|
|
Properties can be set at both the role and server levels.
|
|
|
|
### Role Properties
|
|
|
|
The declaration of a role takes an array of server names and a trailing hash of
|
|
properties. By convention the first server in a role declaration is taken to be the
|
|
primary, but the `:primary` property will not actually be set in such a case.
|
|
|
|
### Server Properties
|
|
|
|
The declaration of a server takes the name of a server and a trailing hash of properties.
|
|
One of those properties must be `:role` and have a value which is an array of role names.
|
|
|
|
### Accessing Properties
|
|
|
|
#### The `roles()` Method
|
|
|
|
The `roles()` method takes one or more role names (or an array of roles) followed by an
|
|
optional [Property Filter](/documentation/advanced-features/property-filtering)) and
|
|
returns an array of `Capistrano::Configuration::Server` objects that belong to those
|
|
roles. These have the following useful attributes:
|
|
|
|
* `hostname` - a String
|
|
* `properties.keys` - the names of the available properties
|
|
* `properties` - a hash-like object that stores the properties.
|
|
It uses Ruby's 'method_missing' to provide a method for each valid key.
|
|
* `roles` - a Set of role names as symbols
|
|
|
|
The servers retrieved by this method are NOT filtered by any host or role filters.
|
|
|
|
#### The `role_properties()` Method
|
|
|
|
This takes a list of roles (followed by an optional [Property
|
|
Filter](/documentation/advanced-features/property-filtering)) and returns an array of
|
|
hashes containing the properties with the keys `:hostname` and `:role` added:
|
|
|
|
```ruby
|
|
task :props do
|
|
rps = role_properties(:redis, :sentinel)
|
|
rps.each do |props|
|
|
puts props.inspect
|
|
end
|
|
end
|
|
|
|
# Produces...
|
|
|
|
{:name=>"resque", :port=>6379, :db=>0, :downtime=>10, :master=>true, :role=>:redis, :hostname=>"dev.local"}
|
|
{:name=>"resque", :port=>6380, :db=>0, :downtime=>10, :role=>:redis, :hostname=>"dev.local"}
|
|
{:port=>26379, :role=>:sentinel, :hostname=>"dev.local"}
|
|
{:port=>26380, :role=>:sentinel, :hostname=>"dev.local"}
|
|
{:port=>26381, :role=>:sentinel, :hostname=>"dev.local"}
|
|
```
|
|
|
|
Alternatively you can supply a block and it will yield the hostname, role and properties:
|
|
|
|
```ruby
|
|
task :props_block do
|
|
role_properties(:sentinel) do |hostname, role, props|
|
|
puts "Host: #{hostname}, Role: #{role}, #{props.inspect}"
|
|
end
|
|
end
|
|
|
|
# Produces...
|
|
|
|
Host: dev.local, Role: sentinel, {:port=>26379}
|
|
Host: dev.local, Role: sentinel, {:port=>26380}
|
|
Host: dev.local, Role: sentinel, {:port=>26381}
|
|
```
|
|
|
|
Note that unlike `on()` this function doesn't cause any remote execution to occur, it is purely for
|
|
configuration purposes.
|