mirror of
https://github.com/capistrano/capistrano
synced 2023-03-27 23:21:18 -04:00
5bae7fb40c
Update CHANGELOG and README Replace HostFilter and RoleFilter with Filter in Configuration Create list of filters from command arguments and ENV vars Intercept the existing on() method to apply external filters Update roles_for() and fetch_primary() to use internal filters
552 lines
15 KiB
Ruby
552 lines
15 KiB
Ruby
require 'spec_helper'
|
|
|
|
describe Capistrano::DSL do
|
|
|
|
let(:dsl) { Class.new.extend Capistrano::DSL }
|
|
|
|
before do
|
|
Capistrano::Configuration.reset!
|
|
end
|
|
|
|
describe 'setting and fetching hosts' do
|
|
describe 'when defining a host using the `server` syntax' do
|
|
before do
|
|
dsl.server 'example1.com', roles: %w{web}, active: true
|
|
dsl.server 'example2.com', roles: %w{web}
|
|
dsl.server 'example3.com', roles: %w{app web}, active: true
|
|
dsl.server 'example4.com', roles: %w{app}, primary: true
|
|
dsl.server 'example5.com', roles: %w{db}, no_release: true
|
|
end
|
|
|
|
describe 'fetching all servers' do
|
|
subject { dsl.roles(:all) }
|
|
|
|
it 'returns all servers' do
|
|
expect(subject.map(&:hostname)).to eq %w{example1.com example2.com example3.com example4.com example5.com}
|
|
end
|
|
end
|
|
|
|
describe 'fetching all release servers' do
|
|
|
|
context 'with no additional options' do
|
|
subject { dsl.release_roles(:all) }
|
|
|
|
it 'returns all release servers' do
|
|
expect(subject.map(&:hostname)).to eq %w{example1.com example2.com example3.com example4.com}
|
|
end
|
|
end
|
|
|
|
context 'with filter options' do
|
|
subject { dsl.release_roles(:all, filter: :active) }
|
|
|
|
it 'returns all release servers that match the filter' do
|
|
expect(subject.map(&:hostname)).to eq %w{example1.com example3.com}
|
|
end
|
|
end
|
|
end
|
|
|
|
describe 'fetching servers by multiple roles' do
|
|
it "does not confuse the last role with options" do
|
|
expect(dsl.roles(:app, :web).count).to eq 4
|
|
expect(dsl.roles(:app, :web, filter: :active).count).to eq 2
|
|
end
|
|
end
|
|
|
|
describe 'fetching servers by role' do
|
|
subject { dsl.roles(:app) }
|
|
|
|
it 'returns the servers' do
|
|
expect(subject.map(&:hostname)).to eq %w{example3.com example4.com}
|
|
end
|
|
end
|
|
|
|
describe 'fetching servers by an array of roles' do
|
|
subject { dsl.roles([:app]) }
|
|
|
|
it 'returns the servers' do
|
|
expect(subject.map(&:hostname)).to eq %w{example3.com example4.com}
|
|
end
|
|
end
|
|
|
|
describe 'fetching filtered servers by role' do
|
|
subject { dsl.roles(:app, filter: :active) }
|
|
|
|
it 'returns the servers' do
|
|
expect(subject.map(&:hostname)).to eq %w{example3.com}
|
|
end
|
|
end
|
|
|
|
describe 'fetching selected servers by role' do
|
|
subject { dsl.roles(:app, select: :active) }
|
|
|
|
it 'returns the servers' do
|
|
expect(subject.map(&:hostname)).to eq %w{example3.com}
|
|
end
|
|
end
|
|
|
|
describe 'fetching the primary server by role' do
|
|
context 'when inferring primary status based on order' do
|
|
subject { dsl.primary(:web) }
|
|
it 'returns the servers' do
|
|
expect(subject.hostname).to eq 'example1.com'
|
|
end
|
|
end
|
|
|
|
context 'when the attribute `primary` is explicity set' do
|
|
subject { dsl.primary(:app) }
|
|
it 'returns the servers' do
|
|
expect(subject.hostname).to eq 'example4.com'
|
|
end
|
|
end
|
|
end
|
|
|
|
describe 'setting an internal host filter' do
|
|
subject { dsl.roles(:app) }
|
|
it 'returns one' do
|
|
dsl.set :filter, { host: 'example3.com' }
|
|
expect(subject.map(&:hostname)).to eq(['example3.com'])
|
|
end
|
|
end
|
|
|
|
describe 'setting an internal role filter' do
|
|
subject { dsl.roles(:app) }
|
|
it 'returns one' do
|
|
dsl.set :filter, { role: :web }
|
|
expect(subject.map(&:hostname)).to eq(['example3.com'])
|
|
end
|
|
end
|
|
|
|
describe 'setting an internal host and role filter' do
|
|
subject { dsl.roles(:app) }
|
|
it 'returns one' do
|
|
dsl.set :filter, { role: :web, host: 'example1.com' }
|
|
expect(subject.map(&:hostname)).to be_empty
|
|
end
|
|
end
|
|
|
|
describe 'setting an internal regexp host filter' do
|
|
subject { dsl.roles(:all) }
|
|
it 'works' do
|
|
dsl.set :filter, { host: /1/ }
|
|
expect(subject.map(&:hostname)).to eq(['example1.com'])
|
|
end
|
|
end
|
|
end
|
|
|
|
describe 'when defining role with reserved name' do
|
|
it 'fails with ArgumentError' do
|
|
expect {
|
|
dsl.role :all, %w{example1.com}
|
|
}.to raise_error(ArgumentError, "all reserved name for role. Please choose another name")
|
|
end
|
|
end
|
|
|
|
describe 'when defining hosts using the `role` syntax' do
|
|
before do
|
|
dsl.role :web, %w{example1.com example2.com example3.com}
|
|
dsl.role :web, %w{example1.com}, active: true
|
|
dsl.role :app, %w{example3.com example4.com}
|
|
dsl.role :app, %w{example3.com}, active: true
|
|
dsl.role :app, %w{example4.com}, primary: true
|
|
dsl.role :db, %w{example5.com}, no_release: true
|
|
end
|
|
|
|
describe 'fetching all servers' do
|
|
subject { dsl.roles(:all) }
|
|
|
|
it 'returns all servers' do
|
|
expect(subject.map(&:hostname)).to eq %w{example1.com example2.com example3.com example4.com example5.com}
|
|
end
|
|
end
|
|
|
|
describe 'fetching all release servers' do
|
|
|
|
context 'with no additional options' do
|
|
subject { dsl.release_roles(:all) }
|
|
|
|
it 'returns all release servers' do
|
|
expect(subject.map(&:hostname)).to eq %w{example1.com example2.com example3.com example4.com}
|
|
end
|
|
end
|
|
|
|
context 'with filter options' do
|
|
subject { dsl.release_roles(:all, filter: :active) }
|
|
|
|
it 'returns all release servers that match the filter' do
|
|
expect(subject.map(&:hostname)).to eq %w{example1.com example3.com}
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
describe 'fetching servers by role' do
|
|
subject { dsl.roles(:app) }
|
|
|
|
it 'returns the servers' do
|
|
expect(subject.map(&:hostname)).to eq %w{example3.com example4.com}
|
|
end
|
|
end
|
|
|
|
describe 'fetching servers by an array of roles' do
|
|
subject { dsl.roles([:app]) }
|
|
|
|
it 'returns the servers' do
|
|
expect(subject.map(&:hostname)).to eq %w{example3.com example4.com}
|
|
end
|
|
end
|
|
|
|
describe 'fetching filtered servers by role' do
|
|
subject { dsl.roles(:app, filter: :active) }
|
|
|
|
it 'returns the servers' do
|
|
expect(subject.map(&:hostname)).to eq %w{example3.com}
|
|
end
|
|
end
|
|
|
|
describe 'fetching selected servers by role' do
|
|
subject { dsl.roles(:app, select: :active) }
|
|
|
|
it 'returns the servers' do
|
|
expect(subject.map(&:hostname)).to eq %w{example3.com}
|
|
end
|
|
end
|
|
|
|
describe 'fetching the primary server by role' do
|
|
context 'when inferring primary status based on order' do
|
|
subject { dsl.primary(:web) }
|
|
it 'returns the servers' do
|
|
expect(subject.hostname).to eq 'example1.com'
|
|
end
|
|
end
|
|
|
|
context 'when the attribute `primary` is explicity set' do
|
|
subject { dsl.primary(:app) }
|
|
it 'returns the servers' do
|
|
expect(subject.hostname).to eq 'example4.com'
|
|
end
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
describe 'when defining a host using a combination of the `server` and `role` syntax' do
|
|
|
|
before do
|
|
dsl.server 'db@example1.com:1234', roles: %w{db}, active: true
|
|
dsl.server 'root@example1.com:1234', roles: %w{web}, active: true
|
|
dsl.server 'example1.com:5678', roles: %w{web}, active: true
|
|
dsl.role :app, %w{deployer@example1.com:1234}
|
|
dsl.role :app, %w{example1.com:5678}
|
|
end
|
|
|
|
describe 'fetching all servers' do
|
|
subject { dsl.roles(:all).map { |server| "#{server.user}@#{server.hostname}:#{server.port}" } }
|
|
|
|
it 'creates a server instance for each unique user@host:port combination' do
|
|
expect(subject).to eq %w{db@example1.com:1234 root@example1.com:1234 @example1.com:5678 deployer@example1.com:1234}
|
|
end
|
|
end
|
|
|
|
describe 'fetching servers for a role' do
|
|
it 'roles defined using the `server` syntax are included' do
|
|
expect(dsl.roles(:web).size).to eq(2)
|
|
end
|
|
|
|
it 'roles defined using the `role` syntax are included' do
|
|
expect(dsl.roles(:app).size).to eq(2)
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
describe 'setting and fetching variables' do
|
|
|
|
before do
|
|
dsl.set :scm, :git
|
|
end
|
|
|
|
context 'without a default' do
|
|
context 'when the variables is defined' do
|
|
it 'returns the variable' do
|
|
expect(dsl.fetch(:scm)).to eq :git
|
|
end
|
|
end
|
|
|
|
context 'when the variables is undefined' do
|
|
it 'returns nil' do
|
|
expect(dsl.fetch(:source_control)).to be_nil
|
|
end
|
|
end
|
|
end
|
|
|
|
context 'with a default' do
|
|
context 'when the variables is defined' do
|
|
it 'returns the variable' do
|
|
expect(dsl.fetch(:scm, :svn)).to eq :git
|
|
end
|
|
end
|
|
|
|
context 'when the variables is undefined' do
|
|
it 'returns the default' do
|
|
expect(dsl.fetch(:source_control, :svn)).to eq :svn
|
|
end
|
|
end
|
|
end
|
|
|
|
context 'with a block' do
|
|
context 'when the variables is defined' do
|
|
it 'returns the variable' do
|
|
expect(dsl.fetch(:scm) { :svn }).to eq :git
|
|
end
|
|
end
|
|
|
|
context 'when the variables is undefined' do
|
|
it 'calls the block' do
|
|
expect(dsl.fetch(:source_control) { :svn }).to eq :svn
|
|
end
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
describe 'asking for a variable' do
|
|
before do
|
|
dsl.ask(:scm, :svn)
|
|
$stdout.stubs(:print)
|
|
end
|
|
|
|
context 'variable is provided' do
|
|
before do
|
|
$stdin.expects(:gets).returns('git')
|
|
end
|
|
|
|
it 'sets the input as the variable' do
|
|
expect(dsl.fetch(:scm)).to eq 'git'
|
|
end
|
|
end
|
|
|
|
context 'variable is not provided' do
|
|
before do
|
|
$stdin.expects(:gets).returns('')
|
|
end
|
|
|
|
it 'sets the variable as the default' do
|
|
expect(dsl.fetch(:scm)).to eq :svn
|
|
end
|
|
end
|
|
end
|
|
|
|
describe 'checking for presence' do
|
|
subject { dsl.any? :linked_files }
|
|
|
|
before do
|
|
dsl.set(:linked_files, linked_files)
|
|
end
|
|
|
|
context 'variable is an non-empty array' do
|
|
let(:linked_files) { %w{1} }
|
|
|
|
it { expect(subject).to be_truthy }
|
|
end
|
|
|
|
context 'variable is an empty array' do
|
|
let(:linked_files) { [] }
|
|
it { expect(subject).to be_falsey }
|
|
end
|
|
|
|
context 'variable exists, is not an array' do
|
|
let(:linked_files) { stub }
|
|
it { expect(subject).to be_truthy }
|
|
end
|
|
|
|
context 'variable is nil' do
|
|
let(:linked_files) { nil }
|
|
it { expect(subject).to be_falsey }
|
|
end
|
|
end
|
|
|
|
describe 'configuration SSHKit' do
|
|
let(:config) { SSHKit.config }
|
|
let(:backend) { SSHKit.config.backend.config }
|
|
let(:default_env) { { rails_env: :production } }
|
|
|
|
before do
|
|
dsl.set(:format, :dot)
|
|
dsl.set(:log_level, :debug)
|
|
dsl.set(:default_env, default_env)
|
|
dsl.set(:pty, true)
|
|
dsl.set(:connection_timeout, 10)
|
|
dsl.set(:ssh_options, {
|
|
keys: %w(/home/user/.ssh/id_rsa),
|
|
forward_agent: false,
|
|
auth_methods: %w(publickey password)
|
|
})
|
|
dsl.configure_backend
|
|
end
|
|
|
|
it 'sets the output' do
|
|
expect(config.output).to be_a SSHKit::Formatter::Dot
|
|
end
|
|
|
|
it 'sets the output verbosity' do
|
|
expect(config.output_verbosity).to eq 0
|
|
end
|
|
|
|
it 'sets the default env' do
|
|
expect(config.default_env).to eq default_env
|
|
end
|
|
|
|
it 'sets the backend pty' do
|
|
expect(backend.pty).to be_truthy
|
|
end
|
|
|
|
it 'sets the backend connection timeout' do
|
|
expect(backend.connection_timeout).to eq 10
|
|
end
|
|
|
|
it 'sets the backend ssh_options' do
|
|
expect(backend.ssh_options[:keys]).to eq %w(/home/user/.ssh/id_rsa)
|
|
expect(backend.ssh_options[:forward_agent]).to eq false
|
|
expect(backend.ssh_options[:auth_methods]).to eq %w(publickey password)
|
|
end
|
|
|
|
end
|
|
|
|
describe 'release path' do
|
|
|
|
before do
|
|
dsl.set(:deploy_to, '/var/www')
|
|
end
|
|
|
|
describe 'fetching release path' do
|
|
subject { dsl.release_path }
|
|
|
|
context 'where no release path has been set' do
|
|
before do
|
|
dsl.delete(:release_path)
|
|
end
|
|
|
|
it 'returns the `current_path` value' do
|
|
expect(subject.to_s).to eq '/var/www/current'
|
|
end
|
|
end
|
|
|
|
context 'where the release path has been set' do
|
|
before do
|
|
dsl.set(:release_path, '/var/www/release_path')
|
|
end
|
|
|
|
it 'returns the set `release_path` value' do
|
|
expect(subject.to_s).to eq '/var/www/release_path'
|
|
end
|
|
end
|
|
end
|
|
|
|
describe 'setting release path' do
|
|
let(:now) { Time.parse("Oct 21 16:29:00 2015") }
|
|
subject { dsl.release_path }
|
|
|
|
context 'without a timestamp' do
|
|
before do
|
|
dsl.env.expects(:timestamp).returns(now)
|
|
dsl.set_release_path
|
|
end
|
|
|
|
it 'returns the release path with the current env timestamp' do
|
|
expect(subject.to_s).to eq '/var/www/releases/20151021162900'
|
|
end
|
|
end
|
|
|
|
context 'with a timestamp' do
|
|
before do
|
|
dsl.set_release_path('timestamp')
|
|
end
|
|
|
|
it 'returns the release path with the timestamp' do
|
|
expect(subject.to_s).to eq '/var/www/releases/timestamp'
|
|
end
|
|
end
|
|
end
|
|
|
|
describe 'setting deploy configuration path' do
|
|
subject { dsl.deploy_config_path.to_s }
|
|
|
|
context 'where no config path is set' do
|
|
before do
|
|
dsl.delete(:deploy_config_path)
|
|
end
|
|
|
|
it 'returns "config/deploy.rb"' do
|
|
expect(subject).to eq 'config/deploy.rb'
|
|
end
|
|
end
|
|
|
|
context 'where a custom path is set' do
|
|
before do
|
|
dsl.set(:deploy_config_path, 'my/custom/path.rb')
|
|
end
|
|
|
|
it 'returns the custom path' do
|
|
expect(subject).to eq 'my/custom/path.rb'
|
|
end
|
|
end
|
|
end
|
|
|
|
describe 'setting stage configuration path' do
|
|
subject { dsl.stage_config_path.to_s }
|
|
|
|
context 'where no config path is set' do
|
|
|
|
before do
|
|
dsl.delete(:stage_config_path)
|
|
end
|
|
|
|
it 'returns "config/deploy"' do
|
|
expect(subject).to eq 'config/deploy'
|
|
end
|
|
end
|
|
|
|
context 'where a custom path is set' do
|
|
before do
|
|
dsl.set(:stage_config_path, 'my/custom/path')
|
|
end
|
|
|
|
it 'returns the custom path' do
|
|
expect(subject).to eq 'my/custom/path'
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
describe 'local_user' do
|
|
before do
|
|
dsl.set :local_user, -> { Etc.getlogin }
|
|
end
|
|
|
|
describe 'fetching local_user' do
|
|
subject { dsl.local_user }
|
|
|
|
context 'where a local_user is not set' do
|
|
before do
|
|
Etc.expects(:getlogin).returns('login')
|
|
end
|
|
|
|
it 'returns the login name' do
|
|
expect(subject.to_s).to eq 'login'
|
|
end
|
|
end
|
|
|
|
context 'where a local_user is set' do
|
|
before do
|
|
dsl.set(:local_user, -> { 'custom login' })
|
|
end
|
|
|
|
it 'returns the custom name' do
|
|
expect(subject.to_s).to eq 'custom login'
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|