whisk_deploy 0.6.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +292 -0
- data/MIT-LICENSE +20 -0
- data/README.integration_specs +24 -0
- data/README.markdown +832 -0
- data/Rakefile +105 -0
- data/VERSION +1 -0
- data/WHY.txt +45 -0
- data/bin/wd +61 -0
- data/bin/wd_role +42 -0
- data/examples/deploy-configs.yml +13 -0
- data/examples/deploy-local.yml +4 -0
- data/examples/deploy-multiple-remotes.yml +26 -0
- data/examples/deploy-staging.yml +8 -0
- data/examples/deploy.rake +11 -0
- data/examples/deploy.yml +16 -0
- data/init.rb +1 -0
- data/install.rb +5 -0
- data/lib/whiskey_disk.rb +327 -0
- data/lib/whiskey_disk/config.rb +127 -0
- data/lib/whiskey_disk/config/abstract_filter.rb +19 -0
- data/lib/whiskey_disk/config/filter.rb +48 -0
- data/lib/whiskey_disk/config/filters/add_environment_name_filter.rb +11 -0
- data/lib/whiskey_disk/config/filters/add_project_name_filter.rb +11 -0
- data/lib/whiskey_disk/config/filters/check_for_duplicate_domains_filter.rb +21 -0
- data/lib/whiskey_disk/config/filters/convert_role_strings_to_list_filter.rb +20 -0
- data/lib/whiskey_disk/config/filters/default_config_target_filter.rb +12 -0
- data/lib/whiskey_disk/config/filters/default_domain_filter.rb +12 -0
- data/lib/whiskey_disk/config/filters/drop_empty_domain_roles_filter.rb +32 -0
- data/lib/whiskey_disk/config/filters/environment_scope_filter.rb +20 -0
- data/lib/whiskey_disk/config/filters/hashify_domain_entries_filter.rb +29 -0
- data/lib/whiskey_disk/config/filters/localize_domains_filter.rb +24 -0
- data/lib/whiskey_disk/config/filters/modules/scope_helper.rb +11 -0
- data/lib/whiskey_disk/config/filters/normalize_ssh_options_filter.rb +29 -0
- data/lib/whiskey_disk/config/filters/project_scope_filter.rb +34 -0
- data/lib/whiskey_disk/config/filters/select_project_and_environment_filter.rb +12 -0
- data/lib/whiskey_disk/config/filters/stringify_hash_keys_filter.rb +25 -0
- data/lib/whiskey_disk/helpers.rb +50 -0
- data/lib/whiskey_disk/rake.rb +47 -0
- data/scenarios/git_repositories/config.git/HEAD +1 -0
- data/scenarios/git_repositories/config.git/config +5 -0
- data/scenarios/git_repositories/config.git/description +1 -0
- data/scenarios/git_repositories/config.git/git-daemon-export-ok +0 -0
- data/scenarios/git_repositories/config.git/hooks/applypatch-msg.sample +15 -0
- data/scenarios/git_repositories/config.git/hooks/commit-msg.sample +24 -0
- data/scenarios/git_repositories/config.git/hooks/post-commit.sample +8 -0
- data/scenarios/git_repositories/config.git/hooks/post-receive.sample +15 -0
- data/scenarios/git_repositories/config.git/hooks/post-update.sample +8 -0
- data/scenarios/git_repositories/config.git/hooks/pre-applypatch.sample +14 -0
- data/scenarios/git_repositories/config.git/hooks/pre-commit.sample +46 -0
- data/scenarios/git_repositories/config.git/hooks/pre-rebase.sample +169 -0
- data/scenarios/git_repositories/config.git/hooks/prepare-commit-msg.sample +36 -0
- data/scenarios/git_repositories/config.git/hooks/update.sample +128 -0
- data/scenarios/git_repositories/config.git/info/exclude +6 -0
- data/scenarios/git_repositories/config.git/objects/0d/b14dd6ddc54017c0a11960dcda82ed802cde69 +0 -0
- data/scenarios/git_repositories/config.git/objects/0e/e781f5ce80d64db32a74a7aae7b5248dafe112 +3 -0
- data/scenarios/git_repositories/config.git/objects/17/6bf54cf17d1d1c24556dc059c4144a5df230e8 +0 -0
- data/scenarios/git_repositories/config.git/objects/20/e9ff3feaa8ede30f707e5f1b4356e3c02bb7ec +0 -0
- data/scenarios/git_repositories/config.git/objects/45/117b1c775f0de415478dbf08ed9d667ab17d13 +0 -0
- data/scenarios/git_repositories/config.git/objects/51/3954c9aca090e6ce40359f0e9fde30ea78eb8c +0 -0
- data/scenarios/git_repositories/config.git/objects/66/947a7a11a6f5d3d561fe95de284ced3010819a +0 -0
- data/scenarios/git_repositories/config.git/objects/6b/bc79311bfac47d3ed724aa82a4814e0dda4c67 +0 -0
- data/scenarios/git_repositories/config.git/objects/71/eb5df52676e8e6efba471050b46978173af110 +1 -0
- data/scenarios/git_repositories/config.git/objects/84/17d2fe3e8fcc0825249c517b29b0f9ea8b8b31 +2 -0
- data/scenarios/git_repositories/config.git/objects/8b/384fcfcf7c0dee7c3c1d5636bee9e645d9cf38 +0 -0
- data/scenarios/git_repositories/config.git/objects/bb/59da633ba74296b0c2f9ff70784ac155ddb599 +0 -0
- data/scenarios/git_repositories/config.git/objects/cc/b86b26189afbf45d8eb9165812ab86dbdfca63 +0 -0
- data/scenarios/git_repositories/config.git/objects/d1/0bcd51fec41f854001e4d61f99d9e282a695d3 +0 -0
- data/scenarios/git_repositories/config.git/objects/d8/a8b0f5b1fd66844efb141d9544965ea0065f2d +0 -0
- data/scenarios/git_repositories/config.git/objects/e6/b02c66ad632e6b8535c4630cb8fe07732a72fc +0 -0
- data/scenarios/git_repositories/config.git/objects/e8/b8bfeeba735c0a1a873082554cb4d7256ac125 +0 -0
- data/scenarios/git_repositories/config.git/objects/f9/0181466a1a60b793ca9cc9abd584c18d4e3887 +0 -0
- data/scenarios/git_repositories/config.git/objects/f9/49d5d8a4f12c91471e34d4e277239c35ebd10d +0 -0
- data/scenarios/git_repositories/config.git/refs/heads/master +1 -0
- data/scenarios/git_repositories/project.git/HEAD +1 -0
- data/scenarios/git_repositories/project.git/config +5 -0
- data/scenarios/git_repositories/project.git/description +1 -0
- data/scenarios/git_repositories/project.git/git-daemon-export-ok +0 -0
- data/scenarios/git_repositories/project.git/hooks/applypatch-msg.sample +15 -0
- data/scenarios/git_repositories/project.git/hooks/commit-msg.sample +24 -0
- data/scenarios/git_repositories/project.git/hooks/post-commit.sample +8 -0
- data/scenarios/git_repositories/project.git/hooks/post-receive.sample +15 -0
- data/scenarios/git_repositories/project.git/hooks/post-update.sample +8 -0
- data/scenarios/git_repositories/project.git/hooks/pre-applypatch.sample +14 -0
- data/scenarios/git_repositories/project.git/hooks/pre-commit.sample +46 -0
- data/scenarios/git_repositories/project.git/hooks/pre-rebase.sample +169 -0
- data/scenarios/git_repositories/project.git/hooks/prepare-commit-msg.sample +36 -0
- data/scenarios/git_repositories/project.git/hooks/update.sample +128 -0
- data/scenarios/git_repositories/project.git/info/exclude +6 -0
- data/scenarios/git_repositories/project.git/objects/04/26e152e66c8cd42974279bdcae09be9839c172 +0 -0
- data/scenarios/git_repositories/project.git/objects/04/f4de85eaf72ef1631dc6d7424045c0a749b757 +1 -0
- data/scenarios/git_repositories/project.git/objects/06/13fe277280cbcdb2856e1eefc70bdaff011b20 +0 -0
- data/scenarios/git_repositories/project.git/objects/06/7aca89b86265eee211387434c3e50f37ccf009 +0 -0
- data/scenarios/git_repositories/project.git/objects/09/445dacc4822722612d60833c9948219ecdd8f5 +0 -0
- data/scenarios/git_repositories/project.git/objects/11/c4ec64326de35462f4e79d0f4229bf8e26e0c5 +0 -0
- data/scenarios/git_repositories/project.git/objects/20/1c7641c2e42b0b904e5c1f793489d8b858e4da +2 -0
- data/scenarios/git_repositories/project.git/objects/23/979639da60d2d31e9744468df1c1221b101e64 +0 -0
- data/scenarios/git_repositories/project.git/objects/27/a3fff2c4c45ab5513a405f694c0a042cb5d417 +1 -0
- data/scenarios/git_repositories/project.git/objects/2c/0c33cfba8e1af15df88522c0db2b10a6a94138 +2 -0
- data/scenarios/git_repositories/project.git/objects/38/b574660305ecb5fec6b2daa7ee1e0dbf1b6003 +0 -0
- data/scenarios/git_repositories/project.git/objects/4a/57abb5e4e426cfc9101b3af22ac83ccbd8e2ad +0 -0
- data/scenarios/git_repositories/project.git/objects/4c/77ebdd985e57afe7988480720c5dc77ec525c9 +0 -0
- data/scenarios/git_repositories/project.git/objects/51/c94da6f1b8aa9d2346088d3d362475b60c7f32 +0 -0
- data/scenarios/git_repositories/project.git/objects/5b/a96acf9cc9b87babe37c032676f53bf1ba9ae7 +2 -0
- data/scenarios/git_repositories/project.git/objects/5d/f555601d60f1c2a84d2364af0ad640612c3ba5 +0 -0
- data/scenarios/git_repositories/project.git/objects/71/03b5ac94940d596c2160a5cfcd55ca4ccac41f +0 -0
- data/scenarios/git_repositories/project.git/objects/73/3fc331098b03523f414f3509b9ae6e637c6866 +0 -0
- data/scenarios/git_repositories/project.git/objects/80/26076649ceccbe96a6292f2432652f08483035 +0 -0
- data/scenarios/git_repositories/project.git/objects/86/d1ef0976be4567de562224e1b51fbf9820c53a +1 -0
- data/scenarios/git_repositories/project.git/objects/87/a9d8b09b3401d21b23d90253332d6b28b47db2 +0 -0
- data/scenarios/git_repositories/project.git/objects/8b/030ba688255c917d189ae3f87d7c5ccd226bc2 +0 -0
- data/scenarios/git_repositories/project.git/objects/95/c9d5ad9b1c90e4c805516783105fc2037dedeb +2 -0
- data/scenarios/git_repositories/project.git/objects/95/d82d043af35a80eabfd56c0d705abfa3488787 +2 -0
- data/scenarios/git_repositories/project.git/objects/96/0bf34bb0b46d0aeb0be87f688f4ef06a4b35e1 +0 -0
- data/scenarios/git_repositories/project.git/objects/a3/860106dc1d148c7831cd45ae38829b4ed47702 +2 -0
- data/scenarios/git_repositories/project.git/objects/a8/506d6439b71784a72ac72d284b2ad53088f573 +0 -0
- data/scenarios/git_repositories/project.git/objects/ad/22ea6c7563777936ecfbe50d8e2cf8120fd525 +0 -0
- data/scenarios/git_repositories/project.git/objects/ae/3900de54aff557c61c81146d00f9d38e55a265 +1 -0
- data/scenarios/git_repositories/project.git/objects/bf/5e3740d52b80abb0378b3f85f93a53b1294521 +1 -0
- data/scenarios/git_repositories/project.git/objects/bf/b59811cdbc069418dee14b171e6e7e979784b7 +0 -0
- data/scenarios/git_repositories/project.git/objects/cc/5ac0afb24e727d5de344cc26a425f4fb7fd17d +3 -0
- data/scenarios/git_repositories/project.git/objects/d1/091aa2dd76885108461110c639e6b33a297fce +0 -0
- data/scenarios/git_repositories/project.git/objects/d8/913f6650eb2b7bf2a633732d8452008ca23dcb +0 -0
- data/scenarios/git_repositories/project.git/objects/db/d1b9667f1b26b13331ac0c321dced8be1aeab0 +3 -0
- data/scenarios/git_repositories/project.git/objects/e4/3b9107e9b1908ce415025e64eb83a493d329b7 +0 -0
- data/scenarios/git_repositories/project.git/objects/ef/2a88894d5421920b9dfe67a9a4d8043830e62e +0 -0
- data/scenarios/git_repositories/project.git/objects/f4/0123a1ff20c65d8dc15a38a83222647908e6f7 +0 -0
- data/scenarios/git_repositories/project.git/objects/f5/0af315b75ca0b12c720dec6d916b76b968c319 +0 -0
- data/scenarios/git_repositories/project.git/objects/f6/0215709b7b23f3738e9cbaf634b1c86bbd376a +0 -0
- data/scenarios/git_repositories/project.git/refs/heads/bad_rakefile +1 -0
- data/scenarios/git_repositories/project.git/refs/heads/hook_with_changed +1 -0
- data/scenarios/git_repositories/project.git/refs/heads/master +1 -0
- data/scenarios/git_repositories/project.git/refs/heads/no_rake_hooks +1 -0
- data/scenarios/git_repositories/project.git/refs/heads/post_rake_tasks +1 -0
- data/scenarios/invalid/deploy.yml +1 -0
- data/scenarios/local/deploy.yml.erb +17 -0
- data/scenarios/remote/deploy.yml +119 -0
- data/scenarios/setup/vagrant/.gitignore +3 -0
- data/scenarios/setup/vagrant/Vagrantfile +10 -0
- data/scenarios/setup/vagrant/manifests/integration.pp +32 -0
- data/scenarios/setup/vagrant/pids/.gitignore +1 -0
- data/spec/.bacon +0 -0
- data/spec/init_spec.rb +9 -0
- data/spec/install_spec.rb +43 -0
- data/spec/integration/branch_switching_spec.rb +41 -0
- data/spec/integration/deployment_failures_spec.rb +106 -0
- data/spec/integration/helper_spec.rb +90 -0
- data/spec/integration/invalid_configuration_spec.rb +39 -0
- data/spec/integration/local_deployments_spec.rb +230 -0
- data/spec/integration/post_rake_tasks_spec.rb +226 -0
- data/spec/integration/post_scripts_spec.rb +246 -0
- data/spec/integration/remote_deployments_spec.rb +166 -0
- data/spec/integration/staleness_checks_spec.rb +72 -0
- data/spec/spec_helper.rb +117 -0
- data/spec/wd_command_spec.rb +986 -0
- data/spec/wd_role_command_spec.rb +49 -0
- data/spec/whiskey_disk/config/filter_spec.rb +77 -0
- data/spec/whiskey_disk/config/filters/add_environment_name_filter_spec.rb +20 -0
- data/spec/whiskey_disk/config/filters/add_project_name_filter_spec.rb +19 -0
- data/spec/whiskey_disk/config/filters/check_for_duplicate_domains_filter_spec.rb +29 -0
- data/spec/whiskey_disk/config/filters/convert_role_strings_to_list_filter_spec.rb +48 -0
- data/spec/whiskey_disk/config/filters/default_config_target_filter_spec.rb +19 -0
- data/spec/whiskey_disk/config/filters/default_domain_filter_spec.rb +18 -0
- data/spec/whiskey_disk/config/filters/drop_empty_domain_roles_filter_spec.rb +60 -0
- data/spec/whiskey_disk/config/filters/environment_scope_filter_spec.rb +32 -0
- data/spec/whiskey_disk/config/filters/hashify_domain_entries_filter_spec.rb +41 -0
- data/spec/whiskey_disk/config/filters/localize_domains_filter_spec.rb +30 -0
- data/spec/whiskey_disk/config/filters/normalize_ssh_options_filter_spec.rb +56 -0
- data/spec/whiskey_disk/config/filters/project_scope_filter_spec.rb +75 -0
- data/spec/whiskey_disk/config/filters/select_project_and_environment_filter_spec.rb +30 -0
- data/spec/whiskey_disk/config/filters/stringify_hash_keys_filter_spec.rb +40 -0
- data/spec/whiskey_disk/config_spec.rb +754 -0
- data/spec/whiskey_disk/helpers_spec.rb +443 -0
- data/spec/whiskey_disk/rake_spec.rb +261 -0
- data/spec/whiskey_disk_spec.rb +1224 -0
- data/tasks/deploy.rake +2 -0
- data/whisk_deploy.gemspec +215 -0
- metadata +241 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_helper.rb'))
|
|
2
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'lib', 'whiskey_disk', 'config'))
|
|
3
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'lib', 'whiskey_disk', 'config', 'filters', 'normalize_ssh_options_filter'))
|
|
4
|
+
|
|
5
|
+
describe 'normalizing SSH options' do
|
|
6
|
+
before do
|
|
7
|
+
@config = WhiskeyDisk::Config.new
|
|
8
|
+
@filter = WhiskeyDisk::Config::NormalizeSshOptionsFilter.new(@config)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it 'eliminates ssh options with nil, or empty values' do
|
|
12
|
+
@data = {
|
|
13
|
+
'domain' => [
|
|
14
|
+
{ 'name' => 'foo', 'ssh_options' => nil },
|
|
15
|
+
{ 'name' => 'bar', 'ssh_options' => '' },
|
|
16
|
+
{ 'name' => 'baz', 'ssh_options' => [] },
|
|
17
|
+
{ 'name' => 'xyzzy', 'ssh_options' => ['', ''] },
|
|
18
|
+
{ 'name' => 'quux', 'ssh_options' => [nil, '', nil] },
|
|
19
|
+
]
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
@filter.filter(@data).should == {
|
|
23
|
+
'domain' => [
|
|
24
|
+
{ 'name' => 'foo' },
|
|
25
|
+
{ 'name' => 'bar' },
|
|
26
|
+
{ 'name' => 'baz' },
|
|
27
|
+
{ 'name' => 'xyzzy' },
|
|
28
|
+
{ 'name' => 'quux' }
|
|
29
|
+
]
|
|
30
|
+
}
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it 'preserves non-empty ssh options' do
|
|
34
|
+
@data = {
|
|
35
|
+
'domain' => [
|
|
36
|
+
{ 'name' => 'foo', 'ssh_options' => nil },
|
|
37
|
+
{ 'name' => 'bar', 'ssh_options' => 'c' },
|
|
38
|
+
{ 'name' => 'baz', 'ssh_options' => [] },
|
|
39
|
+
{ 'name' => 'xyzzy', 'ssh_options' => ['', 'c'] },
|
|
40
|
+
{ 'name' => 'quux', 'ssh_options' => [nil, '', 'a', nil, 'b' ] },
|
|
41
|
+
{ 'name' => 'wut', 'ssh_options' => [nil, '', 'x', 'a', 'a', nil, 'b' ] },
|
|
42
|
+
]
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
@filter.filter(@data).should == {
|
|
46
|
+
'domain' => [
|
|
47
|
+
{ 'name' => 'foo' },
|
|
48
|
+
{ 'name' => 'bar', 'ssh_options' => [ 'c' ] },
|
|
49
|
+
{ 'name' => 'baz' },
|
|
50
|
+
{ 'name' => 'xyzzy', 'ssh_options' => [ 'c' ] },
|
|
51
|
+
{ 'name' => 'quux', 'ssh_options' => [ 'a', 'b' ] },
|
|
52
|
+
{ 'name' => 'wut', 'ssh_options' => [ 'x', 'a', 'a', 'b' ] }
|
|
53
|
+
]
|
|
54
|
+
}
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_helper.rb'))
|
|
2
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'lib', 'whiskey_disk', 'config'))
|
|
3
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'lib', 'whiskey_disk', 'config', 'filters', 'project_scope_filter'))
|
|
4
|
+
|
|
5
|
+
describe 'filtering configuration data by adding project scoping' do
|
|
6
|
+
before do
|
|
7
|
+
ENV['to'] = @env = 'foo:staging'
|
|
8
|
+
|
|
9
|
+
@config = WhiskeyDisk::Config.new
|
|
10
|
+
@filter = WhiskeyDisk::Config::ProjectScopeFilter.new(@config)
|
|
11
|
+
|
|
12
|
+
@bare_data = { 'staging' => { 'repository' => 'git://foo/bar.git', 'domain' => [ { :name => 'ogc@ogtastic.com' } ] } }
|
|
13
|
+
@proj_data = { 'foo' => @bare_data }
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it 'fails if the configuration data is not a hash' do
|
|
17
|
+
lambda { @filter.filter([]) }.should.raise
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
describe 'when no project name is specified via ENV["to"]' do
|
|
21
|
+
before do
|
|
22
|
+
ENV['to'] = @env = 'staging'
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it 'returns the original data if it has both project and environment scoping' do
|
|
26
|
+
@filter.filter(@proj_data).should == @proj_data
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
describe 'when no project name is specified in the bare config hash' do
|
|
30
|
+
it 'returns the original data wrapped in project scope, using a dummy project, if it has environment scoping but no project scoping' do
|
|
31
|
+
@filter.filter(@bare_data).should == { 'unnamed_project' => @bare_data }
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
describe 'when a project name is specified in the bare config hash' do
|
|
36
|
+
before do
|
|
37
|
+
@bare_data['staging']['project'] = 'whiskey_disk'
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it 'returns the original data wrapped in project scope if it has environment scoping but no project scoping' do
|
|
41
|
+
@filter.filter(@bare_data).should == { 'whiskey_disk' => @bare_data }
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
describe 'when a project name is specified via ENV["to"]' do
|
|
47
|
+
before do
|
|
48
|
+
ENV['to'] = @env = 'whiskey_disk:staging'
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
describe 'when a project name is not specified in the bare config hash' do
|
|
52
|
+
it 'returns the original data if it has both project and environment scoping' do
|
|
53
|
+
@filter.filter(@proj_data).should == @proj_data
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it 'returns the original data wrapped in project scope if it has environment scoping but no project scoping' do
|
|
57
|
+
@filter.filter(@bare_data).should == { 'whiskey_disk' => @bare_data }
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
describe 'when a project name is specified in the bare config hash' do
|
|
62
|
+
before do
|
|
63
|
+
@bare_data['staging']['project'] = 'whiskey_disk'
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
it 'returns the original data if it has both project and environment scoping' do
|
|
67
|
+
@filter.filter(@proj_data).should == @proj_data
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
it 'returns the original data wrapped in project scope if it has environment scoping but no project scoping' do
|
|
71
|
+
@filter.filter(@bare_data).should == { 'whiskey_disk' => @bare_data }
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_helper.rb'))
|
|
2
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'lib', 'whiskey_disk', 'config'))
|
|
3
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'lib', 'whiskey_disk', 'config', 'filters', 'select_project_and_environment_filter'))
|
|
4
|
+
|
|
5
|
+
describe 'filtering configuration data by selecting the data for the project and environment' do
|
|
6
|
+
before do
|
|
7
|
+
@config = WhiskeyDisk::Config.new
|
|
8
|
+
@filter = WhiskeyDisk::Config::SelectProjectAndEnvironmentFilter.new(@config)
|
|
9
|
+
|
|
10
|
+
@data = {
|
|
11
|
+
'project' => { 'environment' => { 'a' => 'b' } },
|
|
12
|
+
'other' => { 'missing' => { 'c' => 'd' } },
|
|
13
|
+
}
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it 'fails when the specified project cannot be found' do
|
|
17
|
+
ENV['to'] = @env = 'something:environment'
|
|
18
|
+
lambda { @filter.filter(@data) }.should.raise
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it 'fails when the specified environment cannot be found for the specified project' do
|
|
22
|
+
ENV['to'] = @env = 'other:environment'
|
|
23
|
+
lambda { @filter.filter(@data) }.should.raise
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it 'returns only the data for the specified project and environment' do
|
|
27
|
+
ENV['to'] = @env = 'project:environment'
|
|
28
|
+
@filter.filter(@data).should == @data['project']['environment']
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_helper.rb'))
|
|
2
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'lib', 'whiskey_disk', 'config'))
|
|
3
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'lib', 'whiskey_disk', 'config', 'filters', 'stringify_hash_keys_filter'))
|
|
4
|
+
|
|
5
|
+
describe 'filtering configuration data to only have symbol hash keys' do
|
|
6
|
+
before do
|
|
7
|
+
@config = WhiskeyDisk::Config.new
|
|
8
|
+
@filter = WhiskeyDisk::Config::StringifyHashKeysFilter.new(@config)
|
|
9
|
+
@data = {
|
|
10
|
+
'a' => {
|
|
11
|
+
:x => 'y',
|
|
12
|
+
'c' => 'd',
|
|
13
|
+
:e => {
|
|
14
|
+
'f' => ['a', 'b', 'c']
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
:b => [ '1', '2', '3' ]
|
|
18
|
+
}
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it 'recursively stringifies hash keys in the provided data structure' do
|
|
22
|
+
@filter.filter(@data).should == {
|
|
23
|
+
'a' => {
|
|
24
|
+
'x' => 'y',
|
|
25
|
+
'c' => 'd',
|
|
26
|
+
'e' => {
|
|
27
|
+
'f' => [ 'a', 'b', 'c' ]
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
'b' => [ '1', '2', '3' ]
|
|
31
|
+
}
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it 'clones value data so that the original data structure is not shared' do
|
|
35
|
+
original = @data.clone
|
|
36
|
+
result = @filter.filter(@data)
|
|
37
|
+
result['a']['e']['f'] << 'd'
|
|
38
|
+
@data.should == original
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,754 @@
|
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper.rb'))
|
|
2
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'lib', 'whiskey_disk', 'config'))
|
|
3
|
+
require 'yaml'
|
|
4
|
+
require 'tmpdir'
|
|
5
|
+
require 'fileutils'
|
|
6
|
+
|
|
7
|
+
# create a file at the specified path
|
|
8
|
+
def make(path)
|
|
9
|
+
FileUtils.mkdir_p(File.dirname(path))
|
|
10
|
+
FileUtils.touch(path)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def build_temp_dir
|
|
14
|
+
return Dir.mktmpdir(nil, '/private/tmp') if File.exists?('/private/tmp')
|
|
15
|
+
Dir.mktmpdir
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def write_config_file(data)
|
|
19
|
+
File.open(@config_file, 'w') { |f| f.puts YAML.dump(data) }
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# class for testing .open calls -- for use with URL config paths
|
|
23
|
+
class TestURLConfig < WhiskeyDisk::Config
|
|
24
|
+
def set_response(data)
|
|
25
|
+
@fake_response = YAML.dump(data)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def open(path)
|
|
29
|
+
@fake_response || raise
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
describe WhiskeyDisk::Config do
|
|
34
|
+
before do
|
|
35
|
+
@config = WhiskeyDisk::Config.new
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
describe 'when computing the environment name' do
|
|
39
|
+
it 'returns false when there is no ENV["to"] setting' do
|
|
40
|
+
ENV['to'] = nil
|
|
41
|
+
@config.environment_name.should == false
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it 'returns false when the ENV["to"] setting is blank' do
|
|
45
|
+
ENV['to'] = ''
|
|
46
|
+
@config.environment_name.should == false
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it 'returns the ENV["to"] setting when it is non-blank' do
|
|
50
|
+
ENV['to'] = 'staging'
|
|
51
|
+
@config.environment_name.should == 'staging'
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it 'returns the environment portion of the ENV["to"] setting when a project is specified' do
|
|
55
|
+
ENV['to'] = 'project:staging'
|
|
56
|
+
@config.environment_name.should == 'staging'
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
describe 'when determining whether to do a staleness check before updating' do
|
|
61
|
+
it 'returns false when there is no ENV["check"] setting' do
|
|
62
|
+
ENV['check'] = nil
|
|
63
|
+
@config.check_staleness?.should == false
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
it 'returns false when the ENV["check"] setting is blank' do
|
|
67
|
+
ENV['check'] = ''
|
|
68
|
+
@config.check_staleness?.should == false
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
it 'returns true if the ENV["check"] setting is "t"' do
|
|
72
|
+
ENV['check'] = 't'
|
|
73
|
+
@config.check_staleness?.should == true
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
it 'returns true if the ENV["check"] setting is "true"' do
|
|
77
|
+
ENV['check'] = 'true'
|
|
78
|
+
@config.check_staleness?.should == true
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
it 'returns true if the ENV["check"] setting is "y"' do
|
|
82
|
+
ENV['check'] = 'y'
|
|
83
|
+
@config.check_staleness?.should == true
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
it 'returns true if the ENV["check"] setting is "yes"' do
|
|
87
|
+
ENV['check'] = 'yes'
|
|
88
|
+
@config.check_staleness?.should == true
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
it 'returns true if the ENV["check"] setting is "1"' do
|
|
92
|
+
ENV['check'] = '1'
|
|
93
|
+
@config.check_staleness?.should == true
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
describe 'when determining whether there is a domain limit set' do
|
|
98
|
+
it 'returns false when ENV["only"] is nil' do
|
|
99
|
+
ENV['only'] = nil
|
|
100
|
+
@config.domain_limit.should == false
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
it 'returns false when ENV["only"] is empty' do
|
|
104
|
+
ENV['only'] = ''
|
|
105
|
+
@config.domain_limit.should == false
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
it 'returns the value in ENV["only"] when it is non-empty' do
|
|
109
|
+
ENV['only'] = 'somedomain'
|
|
110
|
+
@config.domain_limit.should == 'somedomain'
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
describe 'when determining whether to turn debug mode on' do
|
|
115
|
+
it 'returns false when there is no ENV["debug"] setting' do
|
|
116
|
+
ENV['debug'] = nil
|
|
117
|
+
@config.debug?.should == false
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
it 'returns false when the ENV["debug"] setting is blank' do
|
|
121
|
+
ENV['debug'] = ''
|
|
122
|
+
@config.debug?.should == false
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
it 'returns true if the ENV["debug"] setting is "t"' do
|
|
126
|
+
ENV['debug'] = 't'
|
|
127
|
+
@config.debug?.should == true
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
it 'returns true if the ENV["debug"] setting is "true"' do
|
|
131
|
+
ENV['debug'] = 'true'
|
|
132
|
+
@config.debug?.should == true
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
it 'returns true if the ENV["debug"] setting is "y"' do
|
|
136
|
+
ENV['debug'] = 'y'
|
|
137
|
+
@config.debug?.should == true
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
it 'returns true if the ENV["debug"] setting is "yes"' do
|
|
141
|
+
ENV['debug'] = 'yes'
|
|
142
|
+
@config.debug?.should == true
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
it 'returns true if the ENV["debug"] setting is "1"' do
|
|
146
|
+
ENV['debug'] = '1'
|
|
147
|
+
@config.debug?.should == true
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
describe 'when fetching configuration' do
|
|
152
|
+
describe 'and path specified is an URL' do
|
|
153
|
+
before do
|
|
154
|
+
ENV['to'] = @env = 'foo:staging'
|
|
155
|
+
ENV['path'] = 'https://www.example.com/foo/bar/deploy.yml'
|
|
156
|
+
@config = TestURLConfig.new
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
it 'fails if the current environment cannot be determined' do
|
|
160
|
+
ENV['to'] = nil
|
|
161
|
+
lambda { @config.fetch }.should.raise
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
it 'fails if the configuration data cannot be retrieved' do
|
|
165
|
+
@config.stub!(:open).and_raise(RuntimeError)
|
|
166
|
+
lambda { @config.fetch }.should.raise
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
it 'fails if the retrieved configuration data is invalid' do
|
|
170
|
+
@config.stub!(:open).and_return("}")
|
|
171
|
+
lambda { @config.fetch }.should.raise
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
it 'fails if the retrieved configuration data does not define data for this environment' do
|
|
175
|
+
@config.set_response('foo' => { 'production' => { 'a' => 'b'} })
|
|
176
|
+
lambda { @config.fetch }.should.raise
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
it 'returns the retrieved configuration yaml data for this environment as a hash' do
|
|
180
|
+
staging = { 'foo' => 'bar', 'repository' => 'xyzzy' }
|
|
181
|
+
@config.set_response('foo' => { 'production' => { 'repository' => 'b'}, 'staging' => staging })
|
|
182
|
+
result = @config.fetch
|
|
183
|
+
staging.each_pair do |k,v|
|
|
184
|
+
result[k].should == v
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
it 'does not include configuration information for other environments in the returned hash' do
|
|
189
|
+
staging = { 'foo' => 'bar', 'baz' => 'xyzzy' }
|
|
190
|
+
@config.set_response('production' => { 'repository' => 'c', 'a' => 'b'}, 'staging' => staging)
|
|
191
|
+
@config.fetch['a'].should.be.nil
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
it 'includes the environment in the hash' do
|
|
195
|
+
staging = { 'foo' => 'bar', 'baz' => 'xyzzy' }
|
|
196
|
+
@config.set_response('foo' => { 'production' => { 'repository' => 'b'}, 'staging' => staging })
|
|
197
|
+
@config.fetch['environment'].should == 'staging'
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
it 'does not allow overriding the environment in the configuration file' do
|
|
201
|
+
staging = { 'foo' => 'bar', 'repository' => 'xyzzy', 'environment' => 'production' }
|
|
202
|
+
@config.set_response('foo' => { 'production' => { 'repository' => 'b'}, 'staging' => staging })
|
|
203
|
+
@config.fetch['environment'].should == 'staging'
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
it 'includes the project handle in the hash' do
|
|
207
|
+
staging = { 'foo' => 'bar', 'repository' => 'xyzzy' }
|
|
208
|
+
@config.set_response('foo' => { 'production' => { 'repository' => 'b'}, 'staging' => staging })
|
|
209
|
+
@config.fetch['project'].should == 'foo'
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
it 'does not allow overriding the project handle in the configuration file when a project root is specified' do
|
|
213
|
+
staging = { 'foo' => 'bar', 'repository' => 'xyzzy', 'project' => 'diskey_whisk' }
|
|
214
|
+
@config.set_response('foo' => { 'production' => { 'repository' => 'b'}, 'staging' => staging })
|
|
215
|
+
@config.fetch['project'].should == 'foo'
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
it 'allows overriding the project handle in the configuration file when a project root is not specified' do
|
|
219
|
+
ENV['to'] = @env = 'staging'
|
|
220
|
+
staging = { 'foo' => 'bar', 'repository' => 'xyzzy', 'project' => 'diskey_whisk' }
|
|
221
|
+
@config.set_response('production' => { 'repository' => 'b'}, 'staging' => staging)
|
|
222
|
+
@config.fetch['project'].should == 'diskey_whisk'
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
it 'includes the environment name as the config_target setting when no config_target is specified' do
|
|
226
|
+
staging = { 'foo' => 'bar', 'repository' => 'xyzzy', 'project' => 'diskey_whisk' }
|
|
227
|
+
@config.set_response('production' => { 'repository' => 'b'}, 'staging' => staging)
|
|
228
|
+
@config.fetch['config_target'].should == 'staging'
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
it 'includes the config_target setting when a config_target is specified' do
|
|
232
|
+
staging = { 'foo' => 'bar', 'repository' => 'xyzzy', 'project' => 'diskey_whisk', 'config_target' => 'testing' }
|
|
233
|
+
@config.set_response('production' => { 'repository' => 'b'}, 'staging' => staging)
|
|
234
|
+
@config.fetch['config_target'].should == 'testing'
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
it 'fails if the named target cannot be found' do
|
|
238
|
+
ENV['to'] = @env = 'bogus:thing'
|
|
239
|
+
lambda { @config.fetch }.should.raise
|
|
240
|
+
end
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
describe 'and path specified is not an URL' do
|
|
244
|
+
before do
|
|
245
|
+
ENV['to'] = @env = 'foo:staging'
|
|
246
|
+
@path = build_temp_dir
|
|
247
|
+
ENV['path'] = @config_file = File.join(@path, 'deploy.yml')
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
after do
|
|
251
|
+
FileUtils.rm_rf(@path)
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
it 'fails if the current environment cannot be determined' do
|
|
255
|
+
ENV['to'] = nil
|
|
256
|
+
lambda { @config.fetch }.should.raise
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
it 'fails if the configuration file does not exist' do
|
|
260
|
+
lambda { @config.fetch }.should.raise
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
it 'fails if the configuration file cannot be read' do
|
|
264
|
+
Dir.mkdir(File.join(@path, 'tmp'))
|
|
265
|
+
lambda { @config.fetch }.should.raise
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
it 'fails if the configuration file is invalid' do
|
|
269
|
+
File.open(@config_file, 'w') {|f| f.puts "}" }
|
|
270
|
+
lambda { @config.fetch }.should.raise
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
it 'fails if the configuration file does not define data for this environment' do
|
|
274
|
+
write_config_file('foo' => { 'production' => { 'a' => 'b'} })
|
|
275
|
+
lambda { @config.fetch }.should.raise
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
it 'returns the configuration yaml file data for this environment as a hash' do
|
|
279
|
+
staging = { 'foo' => 'bar', 'repository' => 'xyzzy' }
|
|
280
|
+
write_config_file('foo' => { 'production' => { 'repository' => 'b'}, 'staging' => staging })
|
|
281
|
+
result = @config.fetch
|
|
282
|
+
staging.each_pair do |k,v|
|
|
283
|
+
result[k].should == v
|
|
284
|
+
end
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
it 'does not include configuration information for other environments in the returned hash' do
|
|
288
|
+
staging = { 'foo' => 'bar', 'baz' => 'xyzzy' }
|
|
289
|
+
write_config_file('production' => { 'repository' => 'c', 'a' => 'b'}, 'staging' => staging)
|
|
290
|
+
@config.fetch['a'].should.be.nil
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
it 'includes the environment in the hash' do
|
|
294
|
+
staging = { 'foo' => 'bar', 'baz' => 'xyzzy' }
|
|
295
|
+
write_config_file('foo' => { 'production' => { 'repository' => 'b'}, 'staging' => staging })
|
|
296
|
+
@config.fetch['environment'].should == 'staging'
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
it 'does not allow overriding the environment in the configuration file' do
|
|
300
|
+
staging = { 'foo' => 'bar', 'repository' => 'xyzzy', 'environment' => 'production' }
|
|
301
|
+
write_config_file('foo' => { 'production' => { 'repository' => 'b'}, 'staging' => staging })
|
|
302
|
+
@config.fetch['environment'].should == 'staging'
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
it 'includes the project handle in the hash' do
|
|
306
|
+
staging = { 'foo' => 'bar', 'repository' => 'xyzzy' }
|
|
307
|
+
write_config_file('foo' => { 'production' => { 'repository' => 'b'}, 'staging' => staging })
|
|
308
|
+
@config.fetch['project'].should == 'foo'
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
it 'does not allow overriding the project handle in the configuration file when a project root is specified' do
|
|
312
|
+
staging = { 'foo' => 'bar', 'repository' => 'xyzzy', 'project' => 'diskey_whisk' }
|
|
313
|
+
write_config_file('foo' => { 'production' => { 'repository' => 'b'}, 'staging' => staging })
|
|
314
|
+
@config.fetch['project'].should == 'foo'
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
it 'allows overriding the project handle in the configuration file when a project root is not specified' do
|
|
318
|
+
ENV['to'] = @env = 'staging'
|
|
319
|
+
staging = { 'foo' => 'bar', 'repository' => 'xyzzy', 'project' => 'diskey_whisk' }
|
|
320
|
+
write_config_file('production' => { 'repository' => 'b'}, 'staging' => staging)
|
|
321
|
+
@config.fetch['project'].should == 'diskey_whisk'
|
|
322
|
+
end
|
|
323
|
+
|
|
324
|
+
it 'includes the environment name as the config_target setting when no config_target is specified' do
|
|
325
|
+
staging = { 'foo' => 'bar', 'repository' => 'xyzzy', 'project' => 'diskey_whisk' }
|
|
326
|
+
write_config_file('production' => { 'repository' => 'b'}, 'staging' => staging)
|
|
327
|
+
@config.fetch['config_target'].should == 'staging'
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
it 'includes the config_target setting when a config_target is specified' do
|
|
331
|
+
staging = { 'foo' => 'bar', 'repository' => 'xyzzy', 'project' => 'diskey_whisk', 'config_target' => 'testing' }
|
|
332
|
+
write_config_file('production' => { 'repository' => 'b'}, 'staging' => staging)
|
|
333
|
+
@config.fetch['config_target'].should == 'testing'
|
|
334
|
+
end
|
|
335
|
+
|
|
336
|
+
it 'fails if the named target cannot be found' do
|
|
337
|
+
ENV['to'] = @env = 'bogus:thing'
|
|
338
|
+
lambda { @config.fetch }.should.raise
|
|
339
|
+
end
|
|
340
|
+
end
|
|
341
|
+
end
|
|
342
|
+
|
|
343
|
+
describe 'returning configuration data from a configuration file' do
|
|
344
|
+
before do
|
|
345
|
+
@path = build_temp_dir
|
|
346
|
+
ENV['path'] = @config_file = File.join(@path, 'deploy.yml')
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
after do
|
|
350
|
+
FileUtils.rm_rf(@path)
|
|
351
|
+
end
|
|
352
|
+
|
|
353
|
+
it 'fails if the configuration file does not exist' do
|
|
354
|
+
lambda { @config.configuration_data }.should.raise
|
|
355
|
+
end
|
|
356
|
+
|
|
357
|
+
it 'returns the contents of the configuration file' do
|
|
358
|
+
File.open(@config_file, 'w') { |f| f.puts "file contents" }
|
|
359
|
+
@config.configuration_data.should == "file contents\n"
|
|
360
|
+
end
|
|
361
|
+
end
|
|
362
|
+
|
|
363
|
+
describe 'loading data from the configuration file' do
|
|
364
|
+
before do
|
|
365
|
+
ENV['to'] = 'foo:bar'
|
|
366
|
+
@path = build_temp_dir
|
|
367
|
+
ENV['path'] = @config_file = File.join(@path, 'deploy.yml')
|
|
368
|
+
end
|
|
369
|
+
|
|
370
|
+
after do
|
|
371
|
+
FileUtils.rm_rf(@path)
|
|
372
|
+
end
|
|
373
|
+
|
|
374
|
+
it 'fails if the configuration data cannot be loaded' do
|
|
375
|
+
lambda { @config.load_data }.should.raise
|
|
376
|
+
end
|
|
377
|
+
|
|
378
|
+
it 'fails if converting the configuration data from YAML fails' do
|
|
379
|
+
File.open(@config_file, 'w') { |f| f.puts "}" }
|
|
380
|
+
lambda { @config.load_data }.should.raise
|
|
381
|
+
end
|
|
382
|
+
|
|
383
|
+
it 'returns the un-YAMLized configuration data' do
|
|
384
|
+
write_config_file('repository' => 'x')
|
|
385
|
+
@config.load_data.should == { 'repository' => 'x' }
|
|
386
|
+
end
|
|
387
|
+
end
|
|
388
|
+
|
|
389
|
+
describe 'computing the project name' do
|
|
390
|
+
it 'returns the project name from the ENV["to"] setting when it is available' do
|
|
391
|
+
ENV['to'] = 'foo:staging'
|
|
392
|
+
@config.project_name.should == 'foo'
|
|
393
|
+
end
|
|
394
|
+
|
|
395
|
+
it 'returns "unnamed_project" when ENV["to"] is unset' do
|
|
396
|
+
ENV['to'] = ''
|
|
397
|
+
@config.project_name.should == 'unnamed_project'
|
|
398
|
+
end
|
|
399
|
+
|
|
400
|
+
it 'returns "unnamed_project" when no ENV["to"] project setting is available' do
|
|
401
|
+
ENV['to'] = 'staging'
|
|
402
|
+
@config.project_name.should == 'unnamed_project'
|
|
403
|
+
end
|
|
404
|
+
end
|
|
405
|
+
|
|
406
|
+
describe 'finding the configuration file' do
|
|
407
|
+
before do
|
|
408
|
+
ENV['to'] = @env = 'staging'
|
|
409
|
+
end
|
|
410
|
+
|
|
411
|
+
describe 'and no path is specified' do
|
|
412
|
+
before do
|
|
413
|
+
ENV['path'] = @path = nil
|
|
414
|
+
@original_path = Dir.pwd
|
|
415
|
+
@base_path = build_temp_dir
|
|
416
|
+
Dir.chdir(@base_path)
|
|
417
|
+
FileUtils.touch(File.join(@base_path, 'Rakefile'))
|
|
418
|
+
@dir = File.join(@base_path, 'config')
|
|
419
|
+
Dir.mkdir(@dir)
|
|
420
|
+
|
|
421
|
+
[
|
|
422
|
+
"/deploy/foo/staging.yml",
|
|
423
|
+
"/deploy/foo.yml",
|
|
424
|
+
"/deploy/staging.yml",
|
|
425
|
+
"/staging.yml",
|
|
426
|
+
"/deploy.yml"
|
|
427
|
+
].each { |file| make(File.join(@dir, file)) }
|
|
428
|
+
end
|
|
429
|
+
|
|
430
|
+
after do
|
|
431
|
+
FileUtils.rm_rf(@base_path)
|
|
432
|
+
Dir.chdir(@original_path)
|
|
433
|
+
end
|
|
434
|
+
|
|
435
|
+
describe 'and a project name is specified in ENV["to"]' do
|
|
436
|
+
before do
|
|
437
|
+
ENV['to'] = @env = 'foo:staging'
|
|
438
|
+
end
|
|
439
|
+
|
|
440
|
+
it 'returns the path to deploy/foo/<environment>.yml under the project base path if it exists' do
|
|
441
|
+
@config.configuration_file.should == "#{@dir}/deploy/foo/staging.yml"
|
|
442
|
+
end
|
|
443
|
+
|
|
444
|
+
it 'returns the path to deploy/foo.yml under the project base path if it exists' do
|
|
445
|
+
File.unlink("#{@dir}/deploy/foo/staging.yml")
|
|
446
|
+
@config.configuration_file.should == "#{@dir}/deploy/foo.yml"
|
|
447
|
+
end
|
|
448
|
+
|
|
449
|
+
it 'returns the path to a per-environment configuration file in the deploy/ directory under the project base path if it exists' do
|
|
450
|
+
File.unlink("#{@dir}/deploy/foo/staging.yml")
|
|
451
|
+
File.unlink("#{@dir}/deploy/foo.yml")
|
|
452
|
+
@config.configuration_file.should == "#{@dir}/deploy/staging.yml"
|
|
453
|
+
end
|
|
454
|
+
|
|
455
|
+
it 'returns the path to a per-environment configuration file under the project base path if it exists' do
|
|
456
|
+
File.unlink("#{@dir}/deploy/foo/staging.yml")
|
|
457
|
+
File.unlink("#{@dir}/deploy/foo.yml")
|
|
458
|
+
File.unlink("#{@dir}/deploy/staging.yml")
|
|
459
|
+
@config.configuration_file.should == "#{@dir}/staging.yml"
|
|
460
|
+
end
|
|
461
|
+
|
|
462
|
+
it 'returns the path to deploy.yml under the project base path' do
|
|
463
|
+
File.unlink("#{@dir}/deploy/foo/staging.yml")
|
|
464
|
+
File.unlink("#{@dir}/deploy/foo.yml")
|
|
465
|
+
File.unlink("#{@dir}/deploy/staging.yml")
|
|
466
|
+
File.unlink("#{@dir}/staging.yml")
|
|
467
|
+
@config.configuration_file.should == "#{@dir}/deploy.yml"
|
|
468
|
+
end
|
|
469
|
+
|
|
470
|
+
it 'fails if no per-environment config file nor deploy.yml exists under the project base path' do
|
|
471
|
+
File.unlink("#{@dir}/deploy/foo/staging.yml")
|
|
472
|
+
File.unlink("#{@dir}/deploy/foo.yml")
|
|
473
|
+
File.unlink("#{@dir}/deploy/staging.yml")
|
|
474
|
+
File.unlink("#{@dir}/staging.yml")
|
|
475
|
+
File.unlink("#{@dir}/deploy.yml")
|
|
476
|
+
lambda { @config.configuration_file }.should.raise
|
|
477
|
+
end
|
|
478
|
+
end
|
|
479
|
+
|
|
480
|
+
describe 'and no project name is specified in ENV["to"]' do
|
|
481
|
+
it 'returns the path to a per-environment configuration file in the deploy/ directory under the project base path if it exists' do
|
|
482
|
+
@config.configuration_file.should == "#{@dir}/deploy/staging.yml"
|
|
483
|
+
end
|
|
484
|
+
|
|
485
|
+
it 'returns the path to a per-environment configuration file under the project base path if it exists' do
|
|
486
|
+
File.unlink("#{@dir}/deploy/staging.yml")
|
|
487
|
+
@config.configuration_file.should == "#{@dir}/staging.yml"
|
|
488
|
+
end
|
|
489
|
+
|
|
490
|
+
it 'returns the path to deploy.yml under the project base path' do
|
|
491
|
+
File.unlink("#{@dir}/deploy/staging.yml")
|
|
492
|
+
File.unlink("#{@dir}/staging.yml")
|
|
493
|
+
@config.configuration_file.should == "#{@dir}/deploy.yml"
|
|
494
|
+
end
|
|
495
|
+
|
|
496
|
+
it 'fails if no per-environment config file nor deploy.yml exists under the project base path' do
|
|
497
|
+
File.unlink("#{@dir}/deploy/staging.yml")
|
|
498
|
+
File.unlink("#{@dir}/staging.yml")
|
|
499
|
+
File.unlink("#{@dir}/deploy.yml")
|
|
500
|
+
lambda { @config.configuration_file }.should.raise
|
|
501
|
+
end
|
|
502
|
+
end
|
|
503
|
+
end
|
|
504
|
+
|
|
505
|
+
describe 'and looking up a file' do
|
|
506
|
+
before do
|
|
507
|
+
@path = build_temp_dir
|
|
508
|
+
ENV['path'] = @config_file = File.join(@path, 'deploy.yml')
|
|
509
|
+
end
|
|
510
|
+
|
|
511
|
+
after do
|
|
512
|
+
FileUtils.rm_rf(@path)
|
|
513
|
+
end
|
|
514
|
+
|
|
515
|
+
it 'fails if a path is specified which does not exist' do
|
|
516
|
+
lambda { @config.configuration_file }.should.raise
|
|
517
|
+
end
|
|
518
|
+
|
|
519
|
+
it 'returns the file path when a path which points to an existing file is specified' do
|
|
520
|
+
FileUtils.touch(@config_file)
|
|
521
|
+
@config.configuration_file.should == @config_file
|
|
522
|
+
end
|
|
523
|
+
end
|
|
524
|
+
|
|
525
|
+
describe 'and a path which points to a directory is specified' do
|
|
526
|
+
before do
|
|
527
|
+
ENV['path'] = @path = build_temp_dir
|
|
528
|
+
|
|
529
|
+
[
|
|
530
|
+
"/deploy/foo/staging.yml",
|
|
531
|
+
"/deploy/foo.yml",
|
|
532
|
+
"/deploy/staging.yml",
|
|
533
|
+
"/staging.yml",
|
|
534
|
+
"/deploy.yml"
|
|
535
|
+
].each { |file| make(File.join(@path, file)) }
|
|
536
|
+
end
|
|
537
|
+
|
|
538
|
+
after do
|
|
539
|
+
FileUtils.rm_rf(@path)
|
|
540
|
+
end
|
|
541
|
+
|
|
542
|
+
describe 'and a project name is specified in ENV["to"]' do
|
|
543
|
+
before do
|
|
544
|
+
ENV['to'] = @env = 'foo:staging'
|
|
545
|
+
end
|
|
546
|
+
|
|
547
|
+
it 'returns the path to deploy/foo/<environment>.yml under the project base path if it exists' do
|
|
548
|
+
@config.configuration_file.should == File.join(@path, 'deploy', 'foo' ,'staging.yml')
|
|
549
|
+
end
|
|
550
|
+
|
|
551
|
+
it 'returns the path to deploy/foo.yml under the project base path if it exists' do
|
|
552
|
+
File.unlink(File.join(@path, 'deploy', 'foo', 'staging.yml'))
|
|
553
|
+
@config.configuration_file.should == File.join(@path, 'deploy', 'foo.yml')
|
|
554
|
+
end
|
|
555
|
+
|
|
556
|
+
it 'returns the path to a per-environment configuration file under deploy/ in the path specified if that file exists' do
|
|
557
|
+
File.unlink(File.join(@path, 'deploy', 'foo', 'staging.yml'))
|
|
558
|
+
File.unlink(File.join(@path, 'deploy', 'foo.yml'))
|
|
559
|
+
@config.configuration_file.should == File.join(@path, 'deploy', 'staging.yml')
|
|
560
|
+
end
|
|
561
|
+
|
|
562
|
+
it 'returns the path to a per-environment configuration file in the path specified if that file exists' do
|
|
563
|
+
File.unlink(File.join(@path, 'deploy', 'foo', 'staging.yml'))
|
|
564
|
+
File.unlink(File.join(@path, 'deploy', 'foo.yml'))
|
|
565
|
+
File.unlink(File.join(@path, 'deploy', 'staging.yml'))
|
|
566
|
+
@config.configuration_file.should == File.join(@path, 'staging.yml')
|
|
567
|
+
end
|
|
568
|
+
|
|
569
|
+
it 'returns the path to deploy.yaml in the path specified if deploy.yml exists' do
|
|
570
|
+
File.unlink(File.join(@path, 'deploy', 'foo', 'staging.yml'))
|
|
571
|
+
File.unlink(File.join(@path, 'deploy', 'foo.yml'))
|
|
572
|
+
File.unlink(File.join(@path, 'deploy', 'staging.yml'))
|
|
573
|
+
File.unlink(File.join(@path, 'staging.yml'))
|
|
574
|
+
@config.configuration_file.should == File.join(@path, 'deploy.yml')
|
|
575
|
+
end
|
|
576
|
+
|
|
577
|
+
it 'fails if no per-environment configuration file nor deploy.yml exists in the path specified' do
|
|
578
|
+
File.unlink(File.join(@path, 'deploy', 'foo', 'staging.yml'))
|
|
579
|
+
File.unlink(File.join(@path, 'deploy', 'foo.yml'))
|
|
580
|
+
File.unlink(File.join(@path, 'deploy', 'staging.yml'))
|
|
581
|
+
File.unlink(File.join(@path, 'staging.yml'))
|
|
582
|
+
File.unlink(File.join(@path, 'deploy.yml'))
|
|
583
|
+
lambda { @config.configuration_file }.should.raise
|
|
584
|
+
end
|
|
585
|
+
end
|
|
586
|
+
|
|
587
|
+
describe 'and no project name is specified in ENV["to"]' do
|
|
588
|
+
it 'returns the path to a per-environment configuration file under deploy/ in the path specified if that file exists' do
|
|
589
|
+
@config.configuration_file.should == File.join(@path, 'deploy', 'staging.yml')
|
|
590
|
+
end
|
|
591
|
+
|
|
592
|
+
it 'returns the path to a per-environment configuration file in the path specified if that file exists' do
|
|
593
|
+
File.unlink(File.join(@path, 'deploy', 'staging.yml'))
|
|
594
|
+
@config.configuration_file.should == File.join(@path, 'staging.yml')
|
|
595
|
+
end
|
|
596
|
+
|
|
597
|
+
it 'returns the path to deploy.yaml in the path specified if deploy.yml exists' do
|
|
598
|
+
File.unlink(File.join(@path, 'deploy', 'staging.yml'))
|
|
599
|
+
File.unlink(File.join(@path, 'staging.yml'))
|
|
600
|
+
@config.configuration_file.should == File.join(@path, 'deploy.yml')
|
|
601
|
+
end
|
|
602
|
+
|
|
603
|
+
it 'fails if no per-environment configuration file nor deploy.yml exists in the path specified' do
|
|
604
|
+
File.unlink(File.join(@path, 'deploy', 'staging.yml'))
|
|
605
|
+
File.unlink(File.join(@path, 'staging.yml'))
|
|
606
|
+
File.unlink(File.join(@path, 'deploy.yml'))
|
|
607
|
+
lambda { @config.configuration_file }.should.raise
|
|
608
|
+
end
|
|
609
|
+
end
|
|
610
|
+
end
|
|
611
|
+
end
|
|
612
|
+
|
|
613
|
+
describe 'filtering configuration data' do
|
|
614
|
+
before do
|
|
615
|
+
ENV['to'] = @env = 'foo:erl'
|
|
616
|
+
@data = {
|
|
617
|
+
'foo' => {
|
|
618
|
+
'xyz' => { 'repository' => 'x' },
|
|
619
|
+
'eee' => { 'repository' => 'x', 'domain' => '' },
|
|
620
|
+
'abc' => { 'repository' => 'x', 'domain' => 'what@example.com' },
|
|
621
|
+
'baz' => { 'repository' => 'x', 'domain' => [ 'bar@example.com', 'baz@domain.com' ]},
|
|
622
|
+
'bar' => { 'repository' => 'x', 'domain' => [ 'user@example.com', nil, 'foo@domain.com' ]},
|
|
623
|
+
'bat' => { 'repository' => 'x', 'domain' => [ 'user@example.com', 'foo@domain.com', '' ]},
|
|
624
|
+
'hsh' => { 'repository' => 'x', 'domain' => [ { 'name' => 'bar@example.com' }, { 'name' => 'baz@domain.com' } ]},
|
|
625
|
+
'mix' => { 'repository' => 'x', 'domain' => [ { 'name' => 'bar@example.com' }, 'baz@domain.com' ]},
|
|
626
|
+
'erl' => { 'repository' => 'x', 'domain' => [ { 'name' => 'bar@example.com', 'roles' => nil },
|
|
627
|
+
{ 'name' => 'baz@domain.com', 'roles' => '' },
|
|
628
|
+
{ 'name' => 'aok@domain.com', 'roles' => [] } ]},
|
|
629
|
+
'rol' => { 'repository' => 'x', 'domain' => [ { 'name' => 'bar@example.com', 'roles' => [ 'web', 'db' ] },
|
|
630
|
+
{ 'name' => 'baz@domain.com', 'roles' => [ 'db' ] },
|
|
631
|
+
{ 'name' => 'aok@domain.com', 'roles' => 'app' } ]},
|
|
632
|
+
'wow' => { 'repository' => 'x', 'domain' => [ { 'name' => 'bar@example.com', 'roles' => [ 'web', 'db' ] },
|
|
633
|
+
{ 'name' => 'baz@domain.com', 'roles' => [ 'db' ] },
|
|
634
|
+
'', 'foo@bar.example.com',
|
|
635
|
+
{ 'name' => 'aok@domain.com', 'roles' => 'app' } ]},
|
|
636
|
+
},
|
|
637
|
+
|
|
638
|
+
'zyx' => {
|
|
639
|
+
'xyz' => { 'repository' => 'x' },
|
|
640
|
+
'eee' => { 'repository' => 'x', 'domain' => '' },
|
|
641
|
+
'abc' => { 'repository' => 'x', 'domain' => 'what@example.com' },
|
|
642
|
+
'hij' => { 'repository' => 'x', 'domain' => [ 'bar@example.com', 'baz@domain.com' ]},
|
|
643
|
+
'def' => { 'repository' => 'x', 'domain' => [ 'user@example.com', nil, 'foo@domain.com' ]},
|
|
644
|
+
'dex' => { 'repository' => 'x', 'domain' => [ 'user@example.com', 'foo@domain.com', '' ]},
|
|
645
|
+
'hsh' => { 'repository' => 'x', 'domain' => [ { 'name' => 'bar@example.com' }, { 'name' => 'baz@domain.com' } ]},
|
|
646
|
+
'mix' => { 'repository' => 'x', 'domain' => [ { 'name' => 'bar@example.com' }, 'baz@domain.com' ]},
|
|
647
|
+
'erl' => { 'repository' => 'x', 'domain' => [ { 'name' => 'bar@example.com', 'roles' => nil },
|
|
648
|
+
{ 'name' => 'baz@domain.com', 'roles' => '' },
|
|
649
|
+
{ 'name' => 'aok@domain.com', 'roles' => [] } ]},
|
|
650
|
+
'rol' => { 'repository' => 'x', 'domain' => [ { 'name' => 'bar@example.com', 'roles' => [ 'web', 'db' ] },
|
|
651
|
+
{ 'name' => 'baz@domain.com', 'roles' => [ 'db' ] },
|
|
652
|
+
{ 'name' => 'aok@domain.com', 'roles' => 'app' } ]},
|
|
653
|
+
'wow' => { 'repository' => 'x', 'domain' => [ { 'name' => 'bar@example.com', 'roles' => [ 'web', 'db' ] },
|
|
654
|
+
{ 'name' => 'baz@domain.com', 'roles' => [ 'db' ] },
|
|
655
|
+
'', 'foo@bar.example.com',
|
|
656
|
+
{ 'name' => 'aok@domain.com', 'roles' => 'app' } ]},
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
end
|
|
660
|
+
|
|
661
|
+
it 'should apply all available filters' do
|
|
662
|
+
@config.filter_data(@data).should == {
|
|
663
|
+
"repository" => "x",
|
|
664
|
+
"project" => "foo",
|
|
665
|
+
"config_target" => "erl",
|
|
666
|
+
"environment" => "erl",
|
|
667
|
+
"domain" => [
|
|
668
|
+
{ 'name' => "bar@example.com" },
|
|
669
|
+
{ 'name' => "baz@domain.com" },
|
|
670
|
+
{ 'name' => "aok@domain.com" }
|
|
671
|
+
]
|
|
672
|
+
}
|
|
673
|
+
end
|
|
674
|
+
end
|
|
675
|
+
|
|
676
|
+
describe 'computing the base path for the project' do
|
|
677
|
+
before do
|
|
678
|
+
@original_path = Dir.pwd
|
|
679
|
+
ENV['path'] = @path = nil
|
|
680
|
+
end
|
|
681
|
+
|
|
682
|
+
after do
|
|
683
|
+
Dir.chdir(@original_path)
|
|
684
|
+
end
|
|
685
|
+
|
|
686
|
+
describe 'and a "path" environment variable is set' do
|
|
687
|
+
before do
|
|
688
|
+
ENV['path'] = @path = build_temp_dir
|
|
689
|
+
@original_path = Dir.pwd
|
|
690
|
+
end
|
|
691
|
+
|
|
692
|
+
after do
|
|
693
|
+
FileUtils.rm_rf(@path)
|
|
694
|
+
Dir.chdir(@original_path)
|
|
695
|
+
end
|
|
696
|
+
|
|
697
|
+
it 'returns the path set in the "path" environment variable' do
|
|
698
|
+
@config.base_path.should == @path
|
|
699
|
+
end
|
|
700
|
+
|
|
701
|
+
it 'leaves the current working path the same as when the base path lookup started' do
|
|
702
|
+
@config.base_path
|
|
703
|
+
Dir.pwd.should == @original_path
|
|
704
|
+
end
|
|
705
|
+
end
|
|
706
|
+
|
|
707
|
+
describe 'and there is no Rakefile in the root path to the current directory' do
|
|
708
|
+
before do
|
|
709
|
+
@original_path = Dir.pwd
|
|
710
|
+
@path = build_temp_dir
|
|
711
|
+
Dir.chdir(@path)
|
|
712
|
+
end
|
|
713
|
+
|
|
714
|
+
after do
|
|
715
|
+
Dir.chdir(@original_path)
|
|
716
|
+
FileUtils.rm_rf(@path)
|
|
717
|
+
end
|
|
718
|
+
|
|
719
|
+
it 'returns the config directory under the current directory if there is no Rakefile along the root path to the current directory' do
|
|
720
|
+
@config.base_path.should == File.join(@path, 'config')
|
|
721
|
+
end
|
|
722
|
+
|
|
723
|
+
it 'leaves the current working path the same as when the base path lookup started' do
|
|
724
|
+
prior = Dir.pwd
|
|
725
|
+
@config.base_path
|
|
726
|
+
Dir.pwd.should == prior
|
|
727
|
+
end
|
|
728
|
+
end
|
|
729
|
+
|
|
730
|
+
describe 'and there is a Rakefile in the root path to the current directory' do
|
|
731
|
+
before do
|
|
732
|
+
@original_path = Dir.pwd
|
|
733
|
+
@path = build_temp_dir
|
|
734
|
+
Dir.chdir(@path)
|
|
735
|
+
FileUtils.touch(File.join(@path, 'Rakefile'))
|
|
736
|
+
end
|
|
737
|
+
|
|
738
|
+
after do
|
|
739
|
+
Dir.chdir(@original_path)
|
|
740
|
+
FileUtils.rm_rf(@path)
|
|
741
|
+
end
|
|
742
|
+
|
|
743
|
+
it 'return the config directory in the nearest enclosing path with a Rakefile along the root path to the current directory' do
|
|
744
|
+
@config.base_path.should == File.join(@path, 'config')
|
|
745
|
+
end
|
|
746
|
+
|
|
747
|
+
it 'leaves the current working path the same as when the base path lookup started' do
|
|
748
|
+
prior = Dir.pwd
|
|
749
|
+
@config.base_path
|
|
750
|
+
Dir.pwd.should == prior
|
|
751
|
+
end
|
|
752
|
+
end
|
|
753
|
+
end
|
|
754
|
+
end
|